import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
// import * as glob from 'glob';
// import * as cp from 'child_process';
// import { log } from 'console';
import archiver from 'archiver';
// import axios from 'axios';
// import * as child_process from 'child_process';
// import * as zlib from 'zlib';
import sharp from 'sharp';
import * as xml2js from 'xml2js';
// import { tgz } from 'compressing';
// import * as compressing from 'compressing';
// const archiver = require('archiver');
import { exec } from 'child_process';
// import { createCanvas, loadImage } from 'canvas';

// 读取 JSON 配置文件
const configPath = path.join(__dirname, '..', 'custom_rules', 'rules.json');
const configData = fs.readFileSync(configPath, 'utf8');
const config = JSON.parse(configData);

const configPath_help = path.join(__dirname, '..', 'custom_rules', 'help.json');
const configData_help = fs.readFileSync(configPath_help, 'utf8');
const config_help = JSON.parse(configData_help);


const single_eventcategory_bank = `
<eventcategory>
    <!-- 这里是klei的build -->
    <name>%{bank}s</name>
    <guid>%{guid1}s</guid>
    <volume_db>0</volume_db>
    <pitch>0</pitch>
    <maxplaybacks>0</maxplaybacks>
    <maxplaybacks_behavior>Steal_oldest</maxplaybacks_behavior>
    <notes></notes>
    <open>0</open>
    %(sub_eventcategory)s
</eventcategory>
`
const single_event_group = `
<eventcategory>
    <!-- 这里是klei的分组 -->
    <name>{group}</name>
    <guid>{guid2}</guid>
    <volume_db>0</volume_db>
    <pitch>0</pitch>
    <maxplaybacks>0</maxplaybacks>
    <maxplaybacks_behavior>Steal_oldest</maxplaybacks_behavior>
    <notes></notes>
    <open>0</open>
</eventcategory>
`

const sounddeffolder = `
<sounddeffolder>
    <name>master</name>
    <guid>%(guid_folder)s</guid>
    <open>0</open>
    <sounddeffolder>
        <!-- 以下是单个声音文件, 只改注释的3处 -->
        <name>__simpleevent_sounddef__</name>
        <guid>%(guid_def)s</guid>
        <open>0</open>
        %(sounddefs)s
    </sounddeffolder>
</sounddeffolder>
`

const single_sounddef = `
<sounddef>
    <!-- 格式: <name>/__simpleevent_sounddef__/文件名_计数器</name> -->
    <name>/__simpleevent_sounddef__/%(wav_name)s_%(num)s</name>
    <guid>%(guid)s</guid>
    <type>randomnorepeat</type>
    <playlistmode>0</playlistmode>
    <randomrepeatsounds>0</randomrepeatsounds>
    <randomrepeatsilences>0</randomrepeatsilences>
    <shuffleglobal>0</shuffleglobal>
    <sequentialrememberposition>0</sequentialrememberposition>
    <sequentialglobal>0</sequentialglobal>
    <spawntime_min>0</spawntime_min>
    <spawntime_max>0</spawntime_max>
    <spawn_max>1</spawn_max>
    <mode>0</mode>
    <pitch>0</pitch>
    <pitch_randmethod>1</pitch_randmethod>
    <pitch_random_min>0</pitch_random_min>
    <pitch_random_max>0</pitch_random_max>
    <pitch_randomization>0</pitch_randomization>
    <pitch_recalculate>0</pitch_recalculate>
    <volume_db>0</volume_db>
    <volume_randmethod>1</volume_randmethod>
    <volume_random_min>0</volume_random_min>
    <volume_random_max>0</volume_random_max>
    <volume_randomization>0</volume_randomization>
    <position_randomization_min>0</position_randomization_min>
    <position_randomization>0</position_randomization>
    <trigger_delay_min>0</trigger_delay_min>
    <trigger_delay_max>0</trigger_delay_max>
    <spawncount>0</spawncount>
    <notes></notes>
    <entrylistmode>1</entrylistmode>
    <waveform>
        <!-- 此处是音频文件的绝对路径  -->
        <filename>%(path)s</filename>
        <!-- 此处的name和文件名保持一致即可  -->
        <soundbankname>%(main_file_name)s</soundbankname>
        <weight>100</weight>
        <percentagelocked>0</percentagelocked>
    </waveform>
</sounddef>
`

const single_eventgroup = `
<eventgroup>
    <!-- group name , 也是路径的中间名  -->
    <name>%(group)s</name>
    <guid>%(guid)s</guid>
    <eventgroup_nextid>0</eventgroup_nextid>
    <event_nextid>0</event_nextid>
    <open>0</open>
    <notes></notes>
    %(simpleevent)s
</eventgroup>
`

const single_simpleevent = `
<simpleevent>
    <event>
        <!-- 音频名  -->
        <name>%(basename)s</name>
        <guid>%(guid)s</guid>
        <parameter_nextid>0</parameter_nextid>
        <layer_nextid>1</layer_nextid>
        <layer>
            <name>layer00</name>
            <height>100</height>
            <envelope_nextid>0</envelope_nextid>
            <mute>0</mute>
            <solo>0</solo>
            <soundlock>0</soundlock>
            <envlock>0</envlock>
            <priority>-1</priority>
            <sound>
                <!-- 格式: <name>/__simpleevent_sounddef__/文件名_计数器</name> !! 注意与上面一致 -->
                <name>/__simpleevent_sounddef__/%(basename)s_%(num)s</name>
                <x>0</x>
                <width>1</width>
                <startmode>0</startmode>
                <!-- 循环 为 0, 只放一次 则为 1 -->
                <loopmode>1</loopmode>
                <loopcount2>-1</loopcount2>
                <autopitchenabled>0</autopitchenabled>
                <autopitchparameter>0</autopitchparameter>
                <autopitchreference>0</autopitchreference>
                <autopitchatzero>0</autopitchatzero>
                <finetune>0</finetune>
                <volume>1</volume>
                <fadeintype>0</fadeintype>
                <fadeouttype>0</fadeouttype>
            </sound>
            <_PC_enable>1</_PC_enable>
            <_XBOX360_enable>1</_XBOX360_enable>
            <_PSP_enable>1</_PSP_enable>
            <_PS3_enable>1</_PS3_enable>
            <_WII_enable>1</_WII_enable>
            <_WiiU_enable>1</_WiiU_enable>
            <_3DS_enable>1</_3DS_enable>
            <_NGP_enable>1</_NGP_enable>
            <_ANDROID_enable>1</_ANDROID_enable>
            <_IOS_enable>1</_IOS_enable>
        </layer>
        <car_rpm>0</car_rpm>
        <car_rpmsmooth>0.075</car_rpmsmooth>
        <car_loadsmooth>0.05</car_loadsmooth>
        <car_loadscale>6</car_loadscale>
        <volume_db>0</volume_db>
        <pitch>0</pitch>
        <pitch_units>Octaves</pitch_units>
        <pitch_randomization>0</pitch_randomization>
        <pitch_randomization_units>Octaves</pitch_randomization_units>
        <volume_randomization>0</volume_randomization>
        <priority>128</priority>
        <maxplaybacks>1</maxplaybacks>
        <maxplaybacks_behavior>Steal_oldest</maxplaybacks_behavior>
        <stealpriority>10000</stealpriority>
        <!-- x_2d 或者 x_3d  -->
        <mode>x_3d</mode>
        <ignoregeometry>No</ignoregeometry>
        <rolloff>Logarithmic</rolloff>
        <mindistance>1</mindistance>
        <maxdistance>10000</maxdistance>
        <auto_distance_filtering>Off</auto_distance_filtering>
        <distance_filter_centre_freq>1500</distance_filter_centre_freq>
        <headrelative>World_relative</headrelative>
        <oneshot>Yes</oneshot>
        <istemplate>No</istemplate>
        <usetemplate></usetemplate>
        <notes></notes>
        <!-- 此处就是上面设置的 catagories 路径 (klei预设) -->
        <category>%(catagories_path)s</category>
        <position_randomization_min>0</position_randomization_min>
        <position_randomization>0</position_randomization>
        <speaker_l>1</speaker_l>
        <speaker_c>0</speaker_c>
        <speaker_r>1</speaker_r>
        <speaker_ls>0</speaker_ls>
        <speaker_rs>0</speaker_rs>
        <speaker_lb>0</speaker_lb>
        <speaker_rb>0</speaker_rb>
        <speaker_lfe>0</speaker_lfe>
        <speaker_config>0</speaker_config>
        <speaker_pan_r>1</speaker_pan_r>
        <speaker_pan_theta>0</speaker_pan_theta>
        <cone_inside_angle>360</cone_inside_angle>
        <cone_outside_angle>360</cone_outside_angle>
        <cone_outside_volumedb>0</cone_outside_volumedb>
        <doppler_scale>1</doppler_scale>
        <reverbdrylevel_db>0</reverbdrylevel_db>
        <reverblevel_db>0</reverblevel_db>
        <speaker_spread>0</speaker_spread>
        <panlevel3d>1</panlevel3d>
        <fadein_time>0</fadein_time>
        <fadeout_time>0</fadeout_time>
        <spawn_intensity>1</spawn_intensity>
        <spawn_intensity_randomization>0</spawn_intensity_randomization>
        <TEMPLATE_PROP_LAYERS>1</TEMPLATE_PROP_LAYERS>
        <TEMPLATE_PROP_KEEP_EFFECTS_PARAMS>1</TEMPLATE_PROP_KEEP_EFFECTS_PARAMS>
        <TEMPLATE_PROP_VOLUME>0</TEMPLATE_PROP_VOLUME>
        <TEMPLATE_PROP_PITCH>1</TEMPLATE_PROP_PITCH>
        <TEMPLATE_PROP_PITCH_RANDOMIZATION>1</TEMPLATE_PROP_PITCH_RANDOMIZATION>
        <TEMPLATE_PROP_VOLUME_RANDOMIZATION>1</TEMPLATE_PROP_VOLUME_RANDOMIZATION>
        <TEMPLATE_PROP_PRIORITY>1</TEMPLATE_PROP_PRIORITY>
        <TEMPLATE_PROP_MAX_PLAYBACKS>1</TEMPLATE_PROP_MAX_PLAYBACKS>
        <TEMPLATE_PROP_MAX_PLAYBACKS_BEHAVIOR>1</TEMPLATE_PROP_MAX_PLAYBACKS_BEHAVIOR>
        <TEMPLATE_PROP_STEAL_PRIORITY>1</TEMPLATE_PROP_STEAL_PRIORITY>
        <TEMPLATE_PROP_MODE>1</TEMPLATE_PROP_MODE>
        <TEMPLATE_PROP_IGNORE_GEOMETRY>1</TEMPLATE_PROP_IGNORE_GEOMETRY>
        <TEMPLATE_PROP_X_3D_ROLLOFF>1</TEMPLATE_PROP_X_3D_ROLLOFF>
        <TEMPLATE_PROP_X_3D_MIN_DISTANCE>1</TEMPLATE_PROP_X_3D_MIN_DISTANCE>
        <TEMPLATE_PROP_X_3D_MAX_DISTANCE>1</TEMPLATE_PROP_X_3D_MAX_DISTANCE>
        <TEMPLATE_PROP_X_3D_POSITION>1</TEMPLATE_PROP_X_3D_POSITION>
        <TEMPLATE_PROP_X_3D_MIN_POSITION_RANDOMIZATION>1</TEMPLATE_PROP_X_3D_MIN_POSITION_RANDOMIZATION>
        <TEMPLATE_PROP_X_3D_POSITION_RANDOMIZATION>1</TEMPLATE_PROP_X_3D_POSITION_RANDOMIZATION>
        <TEMPLATE_PROP_X_3D_CONE_INSIDE_ANGLE>1</TEMPLATE_PROP_X_3D_CONE_INSIDE_ANGLE>
        <TEMPLATE_PROP_X_3D_CONE_OUTSIDE_ANGLE>1</TEMPLATE_PROP_X_3D_CONE_OUTSIDE_ANGLE>
        <TEMPLATE_PROP_X_3D_CONE_OUTSIDE_VOLUME>1</TEMPLATE_PROP_X_3D_CONE_OUTSIDE_VOLUME>
        <TEMPLATE_PROP_X_3D_DOPPLER_FACTOR>1</TEMPLATE_PROP_X_3D_DOPPLER_FACTOR>
        <TEMPLATE_PROP_REVERB_WET_LEVEL>1</TEMPLATE_PROP_REVERB_WET_LEVEL>
        <TEMPLATE_PROP_REVERB_DRY_LEVEL>1</TEMPLATE_PROP_REVERB_DRY_LEVEL>
        <TEMPLATE_PROP_X_3D_SPEAKER_SPREAD>1</TEMPLATE_PROP_X_3D_SPEAKER_SPREAD>
        <TEMPLATE_PROP_X_3D_PAN_LEVEL>1</TEMPLATE_PROP_X_3D_PAN_LEVEL>
        <TEMPLATE_PROP_X_2D_SPEAKER_L>1</TEMPLATE_PROP_X_2D_SPEAKER_L>
        <TEMPLATE_PROP_X_2D_SPEAKER_C>1</TEMPLATE_PROP_X_2D_SPEAKER_C>
        <TEMPLATE_PROP_X_2D_SPEAKER_R>1</TEMPLATE_PROP_X_2D_SPEAKER_R>
        <TEMPLATE_PROP_X_2D_SPEAKER_LS>1</TEMPLATE_PROP_X_2D_SPEAKER_LS>
        <TEMPLATE_PROP_X_2D_SPEAKER_RS>1</TEMPLATE_PROP_X_2D_SPEAKER_RS>
        <TEMPLATE_PROP_X_2D_SPEAKER_LR>1</TEMPLATE_PROP_X_2D_SPEAKER_LR>
        <TEMPLATE_PROP_X_2D_SPEAKER_RR>1</TEMPLATE_PROP_X_2D_SPEAKER_RR>
        <TEMPLATE_PROP_X_SPEAKER_LFE>1</TEMPLATE_PROP_X_SPEAKER_LFE>
        <TEMPLATE_PROP_ONESHOT>1</TEMPLATE_PROP_ONESHOT>
        <TEMPLATE_PROP_FADEIN_TIME>1</TEMPLATE_PROP_FADEIN_TIME>
        <TEMPLATE_PROP_FADEOUT_TIME>1</TEMPLATE_PROP_FADEOUT_TIME>
        <TEMPLATE_PROP_NOTES>1</TEMPLATE_PROP_NOTES>
        <TEMPLATE_PROP_USER_PROPERTIES>1</TEMPLATE_PROP_USER_PROPERTIES>
        <TEMPLATE_PROP_CATEGORY>0</TEMPLATE_PROP_CATEGORY>
        <_PC_enabled>1</_PC_enabled>
        <_XBOX360_enabled>1</_XBOX360_enabled>
        <_PSP_enabled>1</_PSP_enabled>
        <_PS3_enabled>1</_PS3_enabled>
        <_WII_enabled>1</_WII_enabled>
        <_WiiU_enabled>1</_WiiU_enabled>
        <_3DS_enabled>1</_3DS_enabled>
        <_NGP_enabled>1</_NGP_enabled>
        <_ANDROID_enabled>1</_ANDROID_enabled>
        <_IOS_enabled>1</_IOS_enabled>
    </event>
    <playcount>0</playcount>
    <loopcount>0</loopcount>
    <queuedsounds>1</queuedsounds>
    <polyphony>1</polyphony>
    <totalgrains>0</totalgrains>
    <mingraininterval>1</mingraininterval>
    <maxgraininterval>1</maxgraininterval>
    <randomrepeatsounds>0</randomrepeatsounds>
    <randomrepeatsilences>0</randomrepeatsilences>
    <shuffleglobal>0</shuffleglobal>
    <sequentialrememberposition>0</sequentialrememberposition>
    <sequentialglobal>0</sequentialglobal>
    <!-- 此处的name和文件名保持一致即可  -->
    <bankname>%(main_file_name)s</bankname>
    <_PC_resamplemode>Off</_PC_resamplemode>
    <_PC_automaticsampleratepercentage>100</_PC_automaticsampleratepercentage>
    <_PC_fixedsamplerate>48000</_PC_fixedsamplerate>
    <_XBOX360_resamplemode>Off</_XBOX360_resamplemode>
    <_XBOX360_automaticsampleratepercentage>100</_XBOX360_automaticsampleratepercentage>
    <_XBOX360_fixedsamplerate>48000</_XBOX360_fixedsamplerate>
    <_PSP_resamplemode>Off</_PSP_resamplemode>
    <_PSP_automaticsampleratepercentage>100</_PSP_automaticsampleratepercentage>
    <_PSP_fixedsamplerate>48000</_PSP_fixedsamplerate>
    <_PS3_resamplemode>Off</_PS3_resamplemode>
    <_PS3_automaticsampleratepercentage>100</_PS3_automaticsampleratepercentage>
    <_PS3_fixedsamplerate>48000</_PS3_fixedsamplerate>
    <_WII_resamplemode>Off</_WII_resamplemode>
    <_WII_automaticsampleratepercentage>100</_WII_automaticsampleratepercentage>
    <_WII_fixedsamplerate>48000</_WII_fixedsamplerate>
    <_WiiU_resamplemode>Off</_WiiU_resamplemode>
    <_WiiU_automaticsampleratepercentage>100</_WiiU_automaticsampleratepercentage>
    <_WiiU_fixedsamplerate>48000</_WiiU_fixedsamplerate>
    <_3DS_resamplemode>Off</_3DS_resamplemode>
    <_3DS_automaticsampleratepercentage>100</_3DS_automaticsampleratepercentage>
    <_3DS_fixedsamplerate>48000</_3DS_fixedsamplerate>
    <_NGP_resamplemode>Off</_NGP_resamplemode>
    <_NGP_automaticsampleratepercentage>100</_NGP_automaticsampleratepercentage>
    <_NGP_fixedsamplerate>48000</_NGP_fixedsamplerate>
    <_ANDROID_resamplemode>Off</_ANDROID_resamplemode>
    <_ANDROID_automaticsampleratepercentage>100</_ANDROID_automaticsampleratepercentage>
    <_ANDROID_fixedsamplerate>48000</_ANDROID_fixedsamplerate>
    <_IOS_resamplemode>Off</_IOS_resamplemode>
    <_IOS_automaticsampleratepercentage>100</_IOS_automaticsampleratepercentage>
    <_IOS_fixedsamplerate>48000</_IOS_fixedsamplerate>
    <!-- 此处是音频文件的绝对路径  -->
    <unmanagedwaveform>%(path)s</unmanagedwaveform>
</simpleevent>
`

export function activate(context: vscode.ExtensionContext) {
    // 注册命令
    const disposable = vscode.commands.registerCommand('dst-lan.gen-mod', async () => {
        try {
            // 获取当前活动的工作区文件夹
            const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
            if (!workspaceFolder) {
                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.please_open_folder'));
                return;
            }

            // 默认模组名称
            let defaultModName = 'new_mod';

            // 提示用户输入模组名称
            const modName = await vscode.window.showInputBox({
                prompt: vscode.l10n.t('src.extension.entry_mod_name'),
                placeHolder: vscode.l10n.t('src.extension.entry_mod_name_placeholder')
            });

            // 如果用户取消了输入，则不执行任何操作
            if (modName === undefined) {
                return;
            }
            // 如果没输入任何内容，则使用默认模组名称
            if (modName) {
                defaultModName = modName;
            }

            // 源文件夹路径
            const sourceFolder = path.join(__dirname, '..', 'mod_template');

            // wp path
            const wpfolder = path.join(workspaceFolder.uri.fsPath);
            // 目标文件夹路径
            const targetFolder = path.join(wpfolder, defaultModName);

            // 复制文件夹
            await copyFolder(sourceFolder, targetFolder, ['.gitkeep']);

            // 1. 先修改文件内容
            // modinfo
            await rewriteContent(genPath(targetFolder,'modinfo.lua'),{'modid':defaultModName});
            // core/api/_register
            await rewriteContent(genPath(targetFolder,'scripts','core_modid','api','_register.lua'),{'modid':defaultModName});
            // 所有的api
            const callerFiles = getFilesInDirectory(genPath(targetFolder,'scripts','core_modid','callers'));
            let all_callers = '';
            for (const fileName of callerFiles) {
                await rewriteContent(genPath(targetFolder, 'scripts', 'core_modid', 'callers', fileName), {'modid':defaultModName});
                all_callers += `-- modimport('scripts/core_'..modid..'/callers/${fileName}')\n`
            };
            // 所有的LSP
            const LSPFiles_api = getFilesInDirectory(genPath(targetFolder,'LSP','api'));
            for (const fileName of LSPFiles_api) {
                await rewriteContent(genPath(targetFolder, 'LSP','api', fileName), {'modid':defaultModName});
            };
            const LSPFiles_manager = getFilesInDirectory(genPath(targetFolder,'LSP','manager'));
            for (const fileName of LSPFiles_manager) {
                await rewriteContent(genPath(targetFolder, 'LSP','manager', fileName), {'modid':defaultModName});
            };
            // api文件处理
            const apiFiles = getFilesInDirectory(genPath(targetFolder,'scripts','core_modid','api'));
            for (const apiName of apiFiles) {
                await rewriteContent(genPath(targetFolder, 'scripts', 'core_modid', 'api', apiName), {'modid':defaultModName,'modid_upper':defaultModName.toUpperCase()});
            }
            // 所有data
            const dataFiles = getFilesInDirectory(genPath(targetFolder,'scripts','core_modid','data'));
            for (const dataName of dataFiles) {
                await rewriteContent(genPath(targetFolder, 'scripts', 'core_modid', 'data', dataName), {'modid':defaultModName,'modid_upper':defaultModName.toUpperCase()});
            }
            // 所有manager
            const managerFiles = getFilesInDirectory(genPath(targetFolder,'scripts','core_modid','managers'));
            let all_managers = '';
            for (const managerName of managerFiles) {
                await rewriteContent(genPath(targetFolder, 'scripts', 'core_modid', 'managers', managerName), {'modid':defaultModName,'modid_upper':defaultModName.toUpperCase()});
                const {firstLine,secondLine} = await readFirstTwoLines(genPath(targetFolder, 'scripts', 'core_modid', 'managers', managerName));
                // 构建导入语句
                let importStatement = `modimport('scripts/core_${defaultModName}/managers/${managerName}') ${secondLine}`;

                // 判断是否需要添加注释
                if (firstLine.trim() === '-- show') {
                    all_managers += `${importStatement}\n`;
                } else {
                    all_managers += `-- ${importStatement}\n`;
                }
            }
            // 所有component
            const componentFiles = getFilesInDirectory(genPath(targetFolder,'scripts','components'));
            for (const componentName of componentFiles) {
                await rewriteContent(genPath(targetFolder, 'scripts', 'components', componentName), {'modid':defaultModName,'modid_upper':defaultModName.toUpperCase()});
                const replaced_compo_name = await replaceStringAsync(componentName,'modid',defaultModName);
                await renameFile(genPath(targetFolder, 'scripts', 'components', componentName),replaced_compo_name);
            }

            // utils
            const utilsFiles = getFilesInDirectory(genPath(targetFolder,'scripts','core_modid','utils'));
            for (const utilsName of utilsFiles) {
                await rewriteContent(genPath(targetFolder, 'scripts', 'core_modid', 'utils', utilsName), {'modid':defaultModName,'modid_upper':defaultModName.toUpperCase()});
            }
            // api_skins
            await rewriteContent(genPath(targetFolder,'scripts','api_skins','modid_skins.lua'),{'modid':defaultModName,'modid_upper':defaultModName.toUpperCase()});
            await renameFile(genPath(targetFolder,'scripts','api_skins','modid_skins.lua'),`${defaultModName}_skins.lua`);
            await rewriteContent(genPath(targetFolder,'scripts','core_modid','data','unlock_skins.lua'),{'modid':defaultModName,'modid_upper':defaultModName.toUpperCase()});
            await rewriteContent(genPath(targetFolder,'scripts','core_modid','skins','myspear.lua'),{'modid':defaultModName,'modid_upper':defaultModName.toUpperCase()});

            // 为所有prefab加上前缀  修改prefab文件中的内容
            const prefabFiles = getFilesInDirectory(genPath(targetFolder,'scripts','prefabs'),true);
            let all_prefabs = '';
            for (const prefabName of prefabFiles) {
                await rewriteContent(genPath(targetFolder,'scripts', 'prefabs', `${prefabName}.lua`),{'modid':defaultModName});
                await renameFile(genPath(targetFolder,'scripts','prefabs',`${prefabName}.lua`),`${defaultModName}_${prefabName}.lua`);
                all_prefabs += `\t-- '${defaultModName}_${prefabName}',\n`
            };
            // lang
            await rewriteContent(genPath(targetFolder, 'scripts', 'core_modid', 'languages', 'cn.lua'), { 'modid': defaultModName.toUpperCase(), 'modid_upper': defaultModName.toUpperCase() });
            await rewriteContent(genPath(targetFolder, 'scripts', 'core_modid', 'languages', 'en.lua'), { 'modid': defaultModName.toUpperCase(), 'modid_upper': defaultModName.toUpperCase() });
            // modmain
            await rewriteContent(genPath(targetFolder,'modmain.lua'),{'modid':defaultModName,'modid_upper': defaultModName.toUpperCase(),'callers':all_callers,'managers':all_managers,'prefabs':all_prefabs});
            // 2. 修改文件夹名称
            await renameFolder(genPath(targetFolder,'scripts','core_modid'),`core_${defaultModName}`);
            // 修改工作区名字
            await rewriteContent(genPath(targetFolder,'dst_mod-modid-wp.json'),{'modid':defaultModName});
            await renameFile(genPath(targetFolder,'dst_mod-modid-wp.json'),`dst_mod-${defaultModName}.code-workspace`);
            // 介绍
            await rewriteContent(genPath(targetFolder,'lan_modframe.md'),{'modid':defaultModName});

            vscode.window.showInformationMessage(vscode.l10n.t('src.extension.entry_mod_name_success'));
        } catch (error) {
            vscode.window.showErrorMessage(vscode.l10n.t('src.extension.entry_mod_name_fail') + `: ${error}`);
        }
    });

    ///////////
    // 注册切换语言状态的命令
    const disposableToggleLang = vscode.commands.registerCommand('dst-lan.toggle-language', () => {
        toggleLanguage();
    });
    

    function isInsideBrackets(document: vscode.TextDocument, position: vscode.Position, outerRightBracket?: string): boolean {
        const line = document.lineAt(position).text;
        const textBeforePosition = line.substring(0, position.character);
        const textAfterPosition = line.substring(position.character);
    
        const brackets = ['{', '}', '(', ')', '[', ']'];
        const bracketPairs: { [key: string]: string } = {
            '{': '}',
            '(': ')',
            '[': ']'
        };
    
        let openBrackets: { [key: string]: number } = {
            '{': 0,
            '(': 0,
            '[': 0
        };
    
        let closeBrackets: { [key: string]: number } = {
            '}': 0,
            ')': 0,
            ']': 0
        };
    
        // 向左扫描字符
        for (let i = textBeforePosition.length - 1; i >= 0; i--) {
            const char = textBeforePosition[i];
            if (brackets.includes(char)) {
                if (char in openBrackets) {
                    openBrackets[char]++;
                } else if (char in closeBrackets) {
                    const matchingOpenBracket = bracketPairs[char];
                    if (openBrackets[matchingOpenBracket] > 0) {
                        openBrackets[matchingOpenBracket]--;
                    } else if (outerRightBracket && char === outerRightBracket) {
                        // 忽略最外层的右闭括号
                        continue;
                    } else {
                        // 如果没有匹配的开括号，跳出循环
                        break;
                    }
                }
            }
        }
    
        // 向右扫描字符
        for (let i = 0; i < textAfterPosition.length; i++) {
            const char = textAfterPosition[i];
            if (brackets.includes(char)) {
                if (char in closeBrackets) {
                    closeBrackets[char]++;
                } else if (char in openBrackets) {
                    const matchingCloseBracket = bracketPairs[char];
                    if (closeBrackets[matchingCloseBracket] > 0) {
                        closeBrackets[matchingCloseBracket]--;
                    } else if (outerRightBracket && char === bracketPairs[outerRightBracket]) {
                        // 忽略最外层的左开括号
                        continue;
                    } else {
                        // 如果没有匹配的闭括号，跳出循环
                        break;
                    }
                }
            }
        }
    
        // 判断是否在括号内
        const isOutside = Object.values(openBrackets).every(count => count === 0);
        return !isOutside;
    };

    function hasMatchingPair(document: vscode.TextDocument, position: vscode.Position, leftBracket: string, rightBracket: string): boolean {
        const line = document.lineAt(position).text;
        const textBeforePosition = line.substring(0, position.character);
        const textAfterPosition = line.substring(position.character);
    
        // 向左扫描
        let leftScanFoundLeftBracket = false;
        for (let i = textBeforePosition.length - 1; i >= 0; i--) {
            const char = textBeforePosition[i];
            if (char === rightBracket) {
                return false;
            }
            if (char === leftBracket) {
                leftScanFoundLeftBracket = true;
                break;
            }
        }
    
        // 向右扫描
        let rightScanFoundRightBracket = false;
        for (let i = 0; i < textAfterPosition.length; i++) {
            const char = textAfterPosition[i];
            if (char === leftBracket) {
                return false;
            }
            if (char === rightBracket) {
                rightScanFoundRightBracket = true;
                break;
            }
        }
    
        return leftScanFoundLeftBracket && rightScanFoundRightBracket;
    };


    let cur_lang: Promise<string>;
    let lang_author: string;
    cur_lang = readLangFile();
    cur_lang.then((resolvedLang) => {
        lang_author = resolvedLang === 'zh-cn' ? '贡献者' : 'Contributor';
        // 使用 lang_author
    });
    const disposable_custom_regex = vscode.languages.registerCompletionItemProvider(
        { scheme: 'file', language: 'lua' },
        {
            provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
                
                const line = document.lineAt(position);
                const textBeforeCursor = line.text.substring(0, position.character);
                for (const trigger of config.triggers) {
                    const regex = new RegExp(trigger.regex);
                    if (regex.test(textBeforeCursor)) {
                        const { pairs } = trigger;
                         // 检查当前位置是否有对应的括号对
                        if (!hasMatchingPair(document, position, pairs[0], pairs[1])) {
                            // 如果光标位置没有对应的括号对，则不触发补全
                            continue;
                        };
// Text: 0Method: 1Function: 2Constructor: 3Field: 4Variable: 5Class: 6Interface: 7Module: 8Property: 9Unit: 10Value: 11Enum: 12Keyword: 13Snippet: 14Color: 15File: 16Reference: 17Folder: 18EnumMember: 19Constant: 20Struct: 21Event: 22Operator: 23TypeParameter: 24User: 25Issue: 26
                        const completionItems = trigger.items.map((item: { label: string, documentation: string, author: string}) => {
                            // vscode.CompletionItemKind.
                            const completionItem = new vscode.CompletionItem(item.label, trigger.kind); 
                            completionItem.documentation = new vscode.MarkdownString(`${item.documentation} \n\n※${lang_author}: ${item.author}`);
                            return completionItem;
                        });

                        return completionItems;
                    }
                }

                return undefined;
            }
        }, '"', "'", '+' //添加一个加号触发的方法,加号触发时,没有引号,可能会有用
        // ...config.triggers.flatMap((trigger: { regex: string, items: Array<{ label: string, documentation: string, author: string }>, trigger?: string[] }) => 
        // trigger.trigger ? trigger.trigger : ["-", '^'])

    );
    const disposable_help = vscode.languages.registerCompletionItemProvider(
        { scheme: 'file', language: 'lua' },
        {
            provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
                const line = document.lineAt(position);
                const textBeforeCursor = line.text.substring(0, position.character);
                for (const trigger of config_help.triggers) {
                    const regex = new RegExp(trigger.regex);
                    if (regex.test(textBeforeCursor)) {
                        // const { pairs } = trigger;
                       
                        const completionItems = trigger.items.map((item: { label: string, documentation: string, author: string }) => {
                            const completionItem = new vscode.CompletionItem(item.label, vscode.CompletionItemKind.Text);
                            completionItem.documentation = new vscode.MarkdownString(`${item.documentation}`);
                            return completionItem;
                        });

                        return completionItems;
                    }
                }

                return undefined;
            }
        }, '?' 
    );
    ////////////////
    // 注册新的命令用于移除注释
    const disposableRemoveComments = vscode.commands.registerCommand('dst-lan.delete-comments', async () => {
        try {
            const editor = vscode.window.activeTextEditor;
            if (!editor) {
                vscode.window.showErrorMessage('No active text editor found.');
                return;
            }

            const document = editor.document;
            if (document.languageId !== 'lua') {
                vscode.window.showErrorMessage('This command only works with Lua files.');
                return;
            }

            const text = document.getText();
            const newText = removeComments(text);

            // 更新当前文档
            const editBuilder = new vscode.WorkspaceEdit();
            editBuilder.replace(document.uri, new vscode.Range(document.positionAt(0), document.positionAt(text.length)), newText);
            await vscode.workspace.applyEdit(editBuilder);

            vscode.window.showInformationMessage(vscode.l10n.t('src.extension.delete_comment_tips'));
            vscode.window.showInformationMessage(vscode.l10n.t('src.extension.delete_comment'));
        } catch (error) {
            vscode.window.showErrorMessage(`Failed to remove comments: ${error}`);
        }
    });
    //////////////////////////
    const disposableCompiler = vscode.commands.registerCommand('dst-lan.compiler', async () => {
        // 显示快速选择框
        const options = [vscode.l10n.t('src.extension.compiler.switch_docompiler'), vscode.l10n.t('src.extension.compiler.switch_configpath')];
        const selectedOption = await vscode.window.showQuickPick(options);

        if (!selectedOption) {
            return; // 用户取消选择
        }

        switch (selectedOption) {
            case vscode.l10n.t('src.extension.compiler.switch_docompiler'):
                try {
                    const modToolsPath = readConfigFile_compiler();
                    if (!modToolsPath || !checkPathExists_compiler(modToolsPath)) {
                        // 如果配置文件不存在或路径无效，则提示用户配置路径
                        const userPath = await vscode.window.showInputBox({
                            prompt: vscode.l10n.t('src.extension.compiler.firsttime_configpath'),
                            placeHolder: vscode.l10n.t('src.extension.compiler.firsttime_configpath_ph')
                        });
                        // 如果用户取消了输入，则不执行任何操作
                        if (userPath === undefined) {
                            return;
                        };
                        if (userPath && checkPathExists_compiler(userPath)) {
                            // 配置有效路径，并写入配置文件
                            writeConfigFile_compiler(userPath);
                        } else {
                            vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.firsttime_configpath_novalid'));
                            return;
                        };
                    };
                    // 获取当前激活的编辑器
                    const activeEditor = vscode.window.activeTextEditor;
                    if (activeEditor) {
                        // 获取当前编辑器的文件路径
                        const filePath = activeEditor.document.uri.fsPath;
                        const directoryPath = path.dirname(filePath);
                        // 逐级向上查找 modinfo.lua 文件
                        const modInfoDirectory = findModInfoFile(directoryPath);
            
                        if (modInfoDirectory) {
                            
                            vscode.window.showInformationMessage(vscode.l10n.t('src.extension.compiler.compiler_start'));

                            // 读取配置文件
                            const modToolsPath = readConfigFile_compiler();
                            // let modToolsPath: string | null = readConfigFile_compiler();
                            // 检查modToolsPath是否为null或空字符串，并设置默认值
                            // const effectiveModToolsPath = modToolsPath && modToolsPath.trim() !== '' ? modToolsPath : '默认路径';
                            // 获取png.exe
                            const pngExePath = path.join(path.dirname(modToolsPath||''),'png.exe')

                            const pngFilesPath = path.join(modInfoDirectory, 'images');
                            if (fs.existsSync(pngFilesPath)) {
                                const pngFiles = getValidPngFiles(pngFilesPath);
                                if (pngFiles.length > 0) {
                                    // 使用配置好的路径执行命令
                                    for (const pngFile of pngFiles) {
                                        const outputpath = path.dirname(pngFile)
                                        await executeCommand(`"${pngExePath}" "${pngFile}" "${outputpath}"`,vscode.l10n.t('src.extension.compiler.doing'));
                                    }
                                }
                            }

                            const bigportraitsPath = path.join(modInfoDirectory, 'bigportraits');
                            if (fs.existsSync(bigportraitsPath)) {
                                const bigportraits = getValidPngFiles(bigportraitsPath);
                                if (bigportraits.length > 0) {
                                    // 使用配置好的路径执行命令
                                    for (const bigportrait of bigportraits) {
                                        const outputpath = path.dirname(bigportrait)
                                        await executeCommand(`"${pngExePath}" "${bigportrait}" "${outputpath}"`,vscode.l10n.t('src.extension.compiler.doing'));
                                    }
                                }
                            }

                            const levelsPath = path.join(modInfoDirectory, 'levels');
                            if (fs.existsSync(levelsPath)) {
                                const levels = getValidPngFiles(levelsPath);
                                if (levels.length > 0) {
                                    // 使用配置好的路径执行命令
                                    for (const level of levels) {
                                        const outputpath = path.dirname(level)
                                        await executeCommand(`"${pngExePath}" "${level}" "${outputpath}"`,vscode.l10n.t('src.extension.compiler.doing'));
                                    }
                                }
                            }

                            const modiconPath = path.join(modInfoDirectory, 'modicon.png');
                            if (fs.existsSync(modiconPath)) {
                                await executeCommand(`"${pngExePath}" "${modiconPath}" "${modInfoDirectory}"`,vscode.l10n.t('src.extension.compiler.doing'));
                            }

                            // 处理人物图片的 自动改名 
                            if (fs.existsSync(bigportraitsPath)) {
                                const bigportraitsAllFiles = getFilesByRegex(bigportraitsPath,/_none.xml/)
                                if (bigportraitsAllFiles.length > 0) {
                                    // 使用配置好的路径执行命令
                                    for (const bigportraitsSingleFile of bigportraitsAllFiles) {
                                        await replaceInFile(bigportraitsSingleFile,/_none.tex" u1/,"_none_oval.tex\" u1")
                                    }
                                }
                            }
                            // 处理names_
                            const names_Path = path.join(modInfoDirectory, 'images');
                            if (fs.existsSync(names_Path)) {
                                const names_Files = getFilesByRegex(names_Path,/names_.*?\.xml/)
                                if (names_Files.length > 0) {
                                    for (const names_File of names_Files) {
                                        await replaceInFile(names_File,/Element name="names_/,"Element name=\"")
                                    }
                                }
                            }

                            // 处理exported
                            const exportedPath = path.join(modInfoDirectory, 'exported');
                            // vscode.window.showInformationMessage(`exported的目录: ${exportedPath}`);
                            if (fs.existsSync(exportedPath)) {
                                // 获取 exportedPath 下的所有子目录
                                const subdirectories = getSubdirectories(exportedPath);
                                // 在每个子目录中查找 .scml 文件
                                const scmlFiles = findScmlFilesInSubdirectories(subdirectories);

                                if (scmlFiles.length > 0) {
                                    // vscode.window.showInformationMessage(`找到的 .scml 文件路径: ${scmlFiles.join(', ')}`);
                                    // 使用配置好的路径执行命令
                                    for (const scmlFile of scmlFiles) {
                                        // vscode.window.setStatusBarMessage(`正在执行: ${scmlFile}`, 5000); // 设置状态栏消息，持续时间 5 秒
                                        await executeCommand(`"${modToolsPath}" "${scmlFile}" "${modInfoDirectory}"`,vscode.l10n.t('src.extension.compiler.doing'));
                                        // vscode.window.setStatusBarMessage(`执行完毕: ${scmlFile}`, 5000); // 设置状态栏消息，持续时间 5 秒
                                    }
                                    
                                } else {
                                    vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.fail_to_find_scml'));
                                }
                            }

                            vscode.window.showInformationMessage(vscode.l10n.t('src.extension.compiler.success'));

                        } else {
                            vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.fail_to_find_modinfo'));
                        }
                    } else {
                        vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.didnt_open_any_editor'));
                    }
        
                } catch (error) {
                    vscode.window.showErrorMessage(`error: ${error}`);
                    return;
                }
                break;
            case vscode.l10n.t('src.extension.compiler.switch_configpath'):
                try {
                        // if (!modToolsPath || !checkPathExists_compiler(modToolsPath)) {
                            // 如果配置文件不存在或路径无效，则提示用户配置路径
                            const userPath = await vscode.window.showInputBox({
                                prompt: vscode.l10n.t('src.extension.compiler.configpath'),
                                placeHolder: vscode.l10n.t('src.extension.compiler.firsttime_configpath_ph')
                            });
                            // 如果用户取消了输入，则不执行任何操作
                            if (userPath === undefined) {
                                return;
                            }
                            if (userPath && checkPathExists_compiler(userPath)) {
                                // 配置有效路径，并写入配置文件
                                writeConfigFile_compiler(userPath);
                            } else {
                                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.firsttime_configpath_novalid'));
                                return;
                            }
                        // }
                } catch (error) {
                    vscode.window.showErrorMessage(`Failed to execute command: ${error}`);
                    return;
                };
                break;
            default:
                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.novalid_switch'));
                break;
                return;
        };
        return;
    });
    ///////////////////////
    const disposableAvatar = vscode.commands.registerCommand('dst-lan.inject-avatar', async () => {
        const activeEditorPath = getAcitveEditor();
        if (activeEditorPath) { //有激活的编辑器
            const directoryPath = path.dirname(activeEditorPath);

            // 弹出输入框,让玩家输入folderName
            const modfolder = await vscode.window.showInputBox({
                prompt: vscode.l10n.t('src.extension.inject-avatar.folderName'),
                placeHolder: vscode.l10n.t('src.extension.inject-avatar.folderName_ph')
            });
            // 如果用户取消了输入，则不执行任何操作并返回
            if (modfolder === undefined) {return};

            // 如果为空
            if (modfolder === '') {
                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.empty_enter'));
                return;
            };

            // 如果当前文件夹不存在，则提示用户并返回
            if (!fs.existsSync(genPath(directoryPath,modfolder))) {
                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.inject-avatar.current_modpath_not_exist'));
                return;
            };

            // 弹出输入框,让玩家输入modid
            const modID = await vscode.window.showInputBox({
                prompt: vscode.l10n.t('src.extension.inject-avatar.enter_modID'),
                placeHolder: vscode.l10n.t('src.extension.inject-avatar.enter_modID_ph')
            });
            // 如果用户取消了输入，则不执行任何操作并返回
            if (modID === undefined) {return};
            // 如果为空
            if (modID === '') {
                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.empty_enter'));
                return;
            };

            // 弹出输入框,让玩家输入avatar id
            const avatarID = await vscode.window.showInputBox({
                prompt: vscode.l10n.t('src.extension.inject-avatar.enter_avatarID'),
                placeHolder: vscode.l10n.t('src.extension.inject-avatar.enter_avatarID_ph')
            });
            // 如果用户取消了输入，则不执行任何操作并返回
            if (avatarID === undefined) {return};
            // 如果为空
            if (avatarID === '') {
                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.empty_enter'));
                return;
            };

            // 源文件夹路径
            const sourceFolder = path.join(__dirname, '..', 'mod_avatar_template');
            // 目标文件夹路径
            const targetFolder = genPath(directoryPath,modfolder);
            // 复制文件夹
            await copyFolder(sourceFolder, targetFolder, ['.gitkeep']);

            // 重命名图片 bigportraits
            await renameFile(genPath(targetFolder,'bigportraits','avatarid_none.png'),`${avatarID}_none.png`);
            await renameFile(genPath(targetFolder,'bigportraits','avatarid.png'),`${avatarID}.png`);

            // 重命名图片 images/avatars
            await renameFile(genPath(targetFolder,'images','avatars','avatar_avatarid.png'),`avatar_${avatarID}.png`);
            await renameFile(genPath(targetFolder,'images','avatars','avatar_ghost_avatarid.png'),`avatar_ghost_${avatarID}.png`);
            await renameFile(genPath(targetFolder,'images','avatars','self_inspect_avatarid.png'),`self_inspect_${avatarID}.png`);
            // 重命名图片 images/map_icons
            await renameFile(genPath(targetFolder,'images','map_icons','avatarid.png'),`${avatarID}.png`);
            // 重命名图片 images/saveslot_portraits
            await renameFile(genPath(targetFolder,'images','saveslot_portraits','avatarid.png'),`${avatarID}.png`);
            // 重命名图片 images/selectscreen_portraits
            await renameFile(genPath(targetFolder,'images','selectscreen_portraits','avatarid_silho.png'),`${avatarID}_silho.png`);
            await renameFile(genPath(targetFolder,'images','selectscreen_portraits','avatarid.png'),`${avatarID}.png`);
            // 重命名图片 names_avatarid
            await renameFile(genPath(targetFolder,'images','names_avatarid.png'),`names_${avatarID}.png`);

            // 更改exported/avatarid/avatarid.scml 中的占位符
            await rewriteContent(genPath(targetFolder,'exported','avatarid','avatarid.scml'),{'avatarid':avatarID});

            // 重命名exported/avatarid/avatarid.scml
            await renameFile(genPath(targetFolder,'exported','avatarid','avatarid.scml'),`${avatarID}.scml`);
            // 重命名
            await renameFile(genPath(targetFolder,'exported','ghost_avatarid_build','ghost_avatarid_build.scml'),`ghost_${avatarID}_build.scml`);

            // 重命名两个文件夹
            await renameFolder(genPath(targetFolder,'exported','avatarid'),`${avatarID}`);
            await renameFolder(genPath(targetFolder,'exported','ghost_avatarid_build'),`ghost_${avatarID}_build`);

            // scripts
            await rewriteContent(genPath(targetFolder,'scripts','data_avatar','data_avatar_avatarid.lua'),{'avatarid':avatarID,'avatarid_upper':avatarID.toUpperCase(),'modid':modID});
            await rewriteContent(genPath(targetFolder,'scripts','prefabs','avatar_avatarid.lua'),{'avatarid':avatarID,'avatarid_upper':avatarID.toUpperCase(),'modid_upper':modID.toUpperCase(),'modid':modID});

            await renameFile(genPath(targetFolder,'scripts','data_avatar','data_avatar_avatarid.lua'),`data_avatar_${avatarID}.lua`);
            await renameFile(genPath(targetFolder,'scripts','prefabs','avatar_avatarid.lua'),`avatar_${avatarID}.lua`);
            // await renameFile(genPath(targetFolder,'scripts','api_skins','avatarid_skins.lua'),`${avatarID}_skins.lua`);

            

            vscode.window.showInformationMessage(vscode.l10n.t('src.extension.inject-avatar.inject_succeed')+`${avatarID}.lua`);

        } else {
            vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.didnt_open_any_editor'));
            return;
        };
        return;
    })
    /////////////////
    const disposable_makeimg = vscode.commands.registerCommand('dst-lan.makeimg', async () => {
        const activeEditorPath = getAcitveEditor();
        if (activeEditorPath) { //有激活的编辑器
            const directoryPath = path.dirname(activeEditorPath);
            const modInfoDirectory = findModInfoFile(directoryPath);
            if (modInfoDirectory) { // 找到饥荒目录
                //生成临时路径_temp
                const temppath = genFile(path.join(modInfoDirectory,'_temp'));
                // 选项
                const options = [vscode.l10n.t('src.extension.makeimg.done'), vscode.l10n.t('src.extension.makeimg.fetch')];
                const selectedOption = await vscode.window.showQuickPick(options);
                if (!selectedOption) {
                    return; // 用户取消选择
                };
                switch (selectedOption) {
                    case vscode.l10n.t('src.extension.makeimg.done'):{
                        // make sure exported 等文件夹存在
                        const exportedPath = genFile(genPath(modInfoDirectory,'exported'));
                        const imagePath = genFile(genPath(modInfoDirectory,'images'));
                        const invimgPath = genFile(genPath(modInfoDirectory,'images','inventoryimages'));
                        // 弹出输入框,让玩家输入预制物id
                        const prefabName = await vscode.window.showInputBox({
                            prompt: vscode.l10n.t('src.extension.makeimg.enter_prefab_name'),
                            placeHolder: vscode.l10n.t('src.extension.makeimg.enter_prefab_name_ph')
                        });
                        // 如果用户取消了输入，则不执行任何操作并返回
                        if (prefabName === undefined) {return;}
                        // 1.地面
                        if (fs.existsSync(genPath(temppath,'lan_img_ground.png'))){
                            const groundPath = genFile(genPath(modInfoDirectory,'exported',`ground_${prefabName}`));
                            const groundimgPath = genFile(genPath(modInfoDirectory,'exported',`ground_${prefabName}`,'ground'));
                            copyFile(genPath(temppath,'lan_img_ground.png'),genPath(groundimgPath,`${prefabName}.png`));
                            // writeContent(regexRep( readFile(genPathIn()) || '','prefab',prefabName),genPath(groundimgPath,`${prefabName}.scml`));
                            // 写入内容(    正则替换( 读取文件(  内部路径()) || '',  '占位符',替换为),设置scml路径(路径,`${prefabName}.scml`));
                            writeContent(genPath(groundPath,`${prefabName}.scml`),regexRep(readFile(genPathIn('resource','scml','ground.scml'))||'','prefab',prefabName));
                        };
                        // 2.手持
                        const swappng = genPath(temppath,'lan_img_swap.png');
                        if (fs.existsSync(swappng)){
                            const swapPath = genFile(genPath(modInfoDirectory,'exported',`swap_${prefabName}`));
                            const swapimgPath = genFile(genPath(modInfoDirectory,'exported',`swap_${prefabName}`,`swap_${prefabName}`));
                            copyFile(swappng,genPath(swapimgPath,`swap_${prefabName}-0.png`));
                            writeContent(genPath(swapPath,`swap_${prefabName}.scml`),regexRep(readFile(genPathIn('resource','scml','swap.scml'))||'','prefab',prefabName));
                        };
                        // 3.物品栏
                        const invpng = genPath(temppath,'lan_img_inv.png');
                        if (fs.existsSync(invpng)){
                            copyFile(invpng,genPath(invimgPath,`${prefabName}.png`));
                        };

                        // 提示成功
                        vscode.window.showInformationMessage(vscode.l10n.t('src.extension.makeimg.success'));
                        
                    };break;
                    case vscode.l10n.t('src.extension.makeimg.fetch'):{
                        copyFile(genPathIn('resource','prefabimg','lan_img_ground.png'),genPath(temppath,'lan_img_ground.png'));
                        copyFile(genPathIn('resource','prefabimg','lan_img_inv.png'),genPath(temppath,'lan_img_inv.png'));
                        copyFile(genPathIn('resource','prefabimg','lan_img_swap.png'),genPath(temppath,'lan_img_swap.png'));
                        vscode.window.showInformationMessage(vscode.l10n.t('src.extension.makeimg.fetch_done'),vscode.l10n.t('src.extension.makeimg.igotit')).then((buttons) => {
                            if (buttons === vscode.l10n.t('src.extension.makeimg.igotit')) {
                            }
                        });
                        
                        
                    };break; default:
                    vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.novalid_switch'));
                    break;
                    return;
                };
            } else {
                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.fail_to_find_modinfo'));
                return;
            };
        } else {
            vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.didnt_open_any_editor'));
            return;
        };
        return;
    });
    // 注册打包命令
    const disposablePackZIP = vscode.commands.registerCommand('dst-lan.pack-zip', async () => {
        const activeEditorPath = getAcitveEditor();
        if (activeEditorPath) { //有激活的编辑器
            const directoryPath = path.dirname(activeEditorPath);
            const modInfoDirectory = findModInfoFile(directoryPath);
            if (modInfoDirectory) { // 找到饥荒目录
                // const excludeList = ['.github','.vscode','_temp','exported']
                // await compressTest(modInfoDirectory,genPath(modInfoDirectory,'uuuuuu.tgz'))

            } else {
                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.fail_to_find_modinfo'));
                return;
            };
        } else {
            vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.didnt_open_any_editor'));
            return;
        };
        return;
    });
    // extra
    const disposableExtraFn = vscode.commands.registerCommand('dst-lan.extrafn', async () => {
        const activeEditorPath = getAcitveEditor();
        if (activeEditorPath) { //有激活的编辑器
            const directoryPath = path.dirname(activeEditorPath);
            const modInfoDirectory = findModInfoFile(directoryPath);
            if (modInfoDirectory) { // 找到饥荒目录
                const quickpick = vscode.window.createQuickPick();
                quickpick.title = vscode.l10n.t('src.extension.extra.title');
                quickpick.placeholder = vscode.l10n.t('src.extension.extra.ph');
            
                // 定义选项
                quickpick.items = [
                    { label: '0. ', description: '测试按钮', iconPath: {light: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png')),dark: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png'))} },
                    { label: '1. ', description: '---------------------------------------------------',iconPath: {light: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png')),dark: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png'))} },
                    // { label: '1. ', description: vscode.l10n.t('src.extension.extra.op.setpythonpath') },
                    { label: '2. ', description: vscode.l10n.t('src.extension.extra.op.packzip'), iconPath: {light: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png')),dark: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png'))} },
                    { label: '3. ', description: vscode.l10n.t('src.extension.extra.op.expand-crop-canvas'), iconPath: {light: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png')),dark: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png'))} },
                    { label: '4. ', description: vscode.l10n.t('src.extension.extra.op.color-picker'), iconPath: {light: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png')),dark: vscode.Uri.file(genPathIn('icons','dst-logo-32px.png'))} },
                    { label: '5. ', description: vscode.l10n.t('src.extension.extra.op.fdp-gener'), iconPath: {light: vscode.Uri.file(genPathIn('icons','fmod-32px.png')),dark: vscode.Uri.file(genPathIn('icons','fmod-32px.png'))} },
                ];
            
                // 当用户选择一个选项时触发
                quickpick.onDidAccept(async () => {
                    const selectedOption = quickpick.selectedItems[0];
                    if (selectedOption) {
                        switch (selectedOption.label) {
                            case '0. ':{
                                vscode.window.showInformationMessage(`你选择了: ${selectedOption.label}`);
                                break
                            };
                            case '1. ':{
                                // 弹出输入框,让玩家输入pyhton.exe
                                // const pythonpath = await vscode.window.showInputBox({
                                //     prompt: vscode.l10n.t('src.extension.extra.op.setpythonpath'),
                                //     placeHolder: vscode.l10n.t('src.extension.extra.ph')
                                // });
                                // if (!pythonpath) {return};
                                // if (fs.existsSync(pythonpath)){
                                //     await genConfigFile(genPath('pythonpath.ini'),pythonpath)
                                //     vscode.window.showInformationMessage(`${vscode.l10n.t('src.extension.u-set-python-path')} ${pythonpath}`);
                                //     return
                                // } else {
                                //     vscode.window.showInformationMessage(`python.exe ${vscode.l10n.t('src.extension.not-found')}`);
                                //     return
                                // };

                                break
                            };
                            case '2. ': {
                                const quickpick_2 = vscode.window.createQuickPick();
                                quickpick_2.title = vscode.l10n.t('src.extension.extra.op.packzip-choose-title')
                                quickpick_2.placeholder = vscode.l10n.t('src.extension.extra.ph');
                                quickpick_2.items = [
                                    { label: '1. ', description: vscode.l10n.t('src.extension.extra.op.packzip-choose-1-partpack') },
                                    { label: '2. ', description: vscode.l10n.t('src.extension.extra.op.packzip-choose-2-allpack') }
                                ]
                                quickpick_2.onDidAccept(async () => {
                                    const selectedOption_2 = quickpick_2.selectedItems[0];
                                    if (selectedOption_2) {
                                        switch (selectedOption_2.label) {
                                            case '1. ':{
                                                const excludeList = [
                                                    genPath(modInfoDirectory,'.git'),
                                                    genPath(modInfoDirectory,'.vscode'),
                                                    genPath(modInfoDirectory,'_temp'),
                                                    genPath(modInfoDirectory,'_temp_fdp'),
                                                    genPath(modInfoDirectory,'DETAILS'),
                                                    genPath(modInfoDirectory,'exported'),
                                                    genPath(modInfoDirectory,'LSP'),
                                                ];
                                                await packCurrentDirectory(modInfoDirectory,excludeList);
                                                break
                                            };
                                            case '2. ':{
                                                const excludeList = [
                                                    genPath(modInfoDirectory,'.git'),
                                                    genPath(modInfoDirectory,'.vscode'),
                                                    genPath(modInfoDirectory,'_temp'),
                                                    genPath(modInfoDirectory,'_temp_fdp'),
                                                    genPath(modInfoDirectory,'DETAILS'),
                                                    // genPath(modInfoDirectory,'exported'),
                                                    // genPath(modInfoDirectory,'LSP'),
                                                ];
                                                await packCurrentDirectory(modInfoDirectory,excludeList);
                                                break
                                            }
                                        }
                                    }
                                    quickpick_2.dispose();
                                })
                                quickpick_2.show();
                                break
                            };
                            case '3. ':{
                                // const {orig_width, orig_height} = await expandCanvasForce(genPath(modInfoDirectory,'modicon.png'));
                                // await modifyXmlFile(genPath(modInfoDirectory,'exported','lol_wp_s13_collector','lol_wp_s13_collector.scml'));
                                // await op_expand_all(genPath(modInfoDirectory,'exported','lol_wp_s13_collector','lol_wp_s13_collector.scml'));
                                // break
                                const quickpick_3 = vscode.window.createQuickPick();
                                quickpick_3.title = vscode.l10n.t('src.extension.extra.op.expand-choose-title');
                                quickpick_3.placeholder = vscode.l10n.t('src.extension.extra.ph');
                                quickpick_3.items = [
                                    { label: '0. ', description: 'Never Mind!' },
                                    { label: '1. ', description: vscode.l10n.t('src.extension.extra.op.expand-choose-1-expand') },
                                    { label: '2. ', description: vscode.l10n.t('src.extension.extra.op.expand-choose-2-crop') },
                                ];
                                quickpick_3.onDidAccept(async () => {
                                    const selectedOption_3 = quickpick_3.selectedItems[0];
                                    if (selectedOption_3) {
                                        switch (selectedOption_3.label) {
                                            case '0. ':{
                                                break
                                            };
                                            case '1. ':{
                                                const scmlPath = await selectScmlFile();
                                                if (!scmlPath) {
                                                    return;
                                                } else {
                                                    await op_expand_all(scmlPath);
                                                }
                                                break
                                            };
                                            case '2. ':{
                                                // await cropCanvasForce(genPath(modInfoDirectory,'exported','lol_wp_s13_collector','lol_wp_s13_collector','lol_wp_s13_collector_2.png'))
                                                const scmlPath = await selectScmlFile();
                                                console.log(scmlPath);
                                                if (!scmlPath) {
                                                    return;
                                                } else {
                                                    await op_crop_all(scmlPath);
                                                }
                                                break
                                            };
                                        }
                                    }
                                    quickpick_3.dispose();
                                });
                                quickpick_3.show();
                                break
                            };
                            case '4. ':{
                                const panel = vscode.window.createWebviewPanel(
                                    'colorPicker',
                                    'Color Picker',
                                    vscode.ViewColumn.One,
                                    {}
                                );
                            
                                panel.webview.html = /*html*/`
                                    <!DOCTYPE html>
                                    <html lang="en">
                                    <head>
                                        <meta charset="UTF-8">
                                        <meta name="viewport" content="width=device-width, initial-scale=1.0">
                                        <title>Color Picker</title>
                                        <style>
                                            body {
                                                font-family: Arial, sans-serif;
                                                margin: 0;
                                                padding: 10px;
                                                background-color: #303030;
                                                color: #ffffff;
                                                display: flex;
                                                flex-direction: column;
                                                align-items: flex-start; /* 左对齐 */
                                            }
                                            input[type="color"] {
                                                border: thin solid #303030; /* 调整边框样式 */
                                                width: 80px; /* 设置宽度 */
                                                height: 60px; /* 设置高度 */
                                                border-radius: 4px; /* 移除圆角以呈现矩形 */
                                            }
                                            .hint {
                                                margin-top: 5px;
                                                font-size: 14px;
                                                color: #aaaaaa;
                                            }
                                        </style>
                                    </head>
                                    <body>
                                        <input type="color" id="colorPicker">
                                        <div class="hint">Pick Color</div>
                                        <script>
                                            const vscode = acquireVsCodeApi();
                                            document.getElementById('colorPicker').addEventListener('input', (event) => {
                                                vscode.postMessage({
                                                    command: 'colorSelected',
                                                    color: event.target.value
                                                });
                                            });
                                        </script>
                                    </body>
                                    </html>
                                `;
                            
                                panel.webview.onDidReceiveMessage(message => {
                                    if (message.command === 'colorSelected') {
                                        vscode.window.showInformationMessage(`Selected color: ${message.color}`);
                                    }
                                }, undefined, context.subscriptions);
                                break
                            };
                            case '5. ':{
                                // const temppath = genFile(path.join(modInfoDirectory,'_temp_fdp'));

                                // 复制文件夹
                                await copyFolder(path.join(__dirname, '..', 'resource', '_temp_fdp'), path.join(modInfoDirectory,'_temp_fdp'), ['.gitkeep']);

                                const quickpick_5 = vscode.window.createQuickPick();
                                quickpick_5.title = vscode.l10n.t('src.extension.extra.op.fdp-gener-title');
                                quickpick_5.placeholder = vscode.l10n.t('src.extension.extra.ph');
                                quickpick_5.items = [
                                    { label: '0. ', description: 'Never Mind!' },
                                    { label: '1. ', description: vscode.l10n.t('src.extension.extra.op.fdp-gener-go') },
                                    { label: '2. ', description: vscode.l10n.t('src.extension.extra.op.fdp-gener-makesure-temp') },
                                ];
                                quickpick_5.onDidAccept(async () => {
                                    const selectedOption_3 = quickpick_5.selectedItems[0];
                                    if (selectedOption_3) {
                                        switch (selectedOption_3.label) {
                                            case '0. ':{
                                                break
                                            };
                                            case '1. ':{
                                                const allFiles = await getAllFilesRecursively(genPath(modInfoDirectory,'_temp_fdp'));
                                                console.log(allFiles);

                                                const dict1: Record<string, {fsb_name: string, group: string, klei_bank: string, klei_group: string, soundname: string, basename: string, fullpath: string}[]> = {};

                                                for (const file of allFiles) {
                                                    const result = await parseTempFdpPath(file);
                                                    if (result) {
                                                        // 如果该 fsb_name 还不存在，则初始化为空数组
                                                        if (!dict1[result.fsb_name]) {
                                                            dict1[result.fsb_name] = [];
                                                        }
                                                        dict1[result.fsb_name].push(result);
                                                    } else {}
                                                }
                                                for (const fsbname in dict1) { 
                                                    const fdp_path = genPath(modInfoDirectory,'_temp_fdp',`${fsbname}.fdp`)
                                                    await copyFile(path.join(__dirname, '..', 'resource', 'fdp_gen.fdp'), fdp_path);
                                                    // 官方目录
                                                    const category: Record<string, Record<string, {fsb_name: string, group: string, klei_bank: string, klei_group: string, soundname: string, basename: string, fullpath: string}[]>> = {};

                                                    const custom_group: Record<string, {fsb_name: string, group: string, klei_bank: string, klei_group: string, soundname: string, basename: string, fullpath: string}[]> = {};
                                                    // 音频文件数量
                                                    let filenums: number = 0;
                                                    
                                                    for (const soundfile of dict1[fsbname]) { 
                                                        filenums += 1;
                                                        const klei_bank = soundfile.klei_bank
                                                        const klei_group = soundfile.klei_group
                                                        const group = soundfile.group
                                                        if (!category[klei_bank]) {
                                                            category[klei_bank] = {}
                                                        }
                                                        if (!category[klei_bank][klei_group]) {
                                                            category[klei_bank][klei_group] = []
                                                        }
                                                        if (!custom_group[group]) {
                                                            custom_group[group] = []
                                                        }
                                                        category[klei_bank][klei_group].push(soundfile);
                                                        custom_group[group].push(soundfile);
                                                    }
                                                    // 所有 eventcategory
                                                    let all_rep_event_group: string = ''
                                                    for (const bank in category) {
                                                        let rep_event_group: string = ''
                                                        for (const group in category[bank]) {
                                                            rep_event_group += replacePlaceholders(single_event_group,{'group': group, 'guid2': generateUUIDWithTime()});
                                                        };
                                                        rep_event_group = replacePlaceholders(single_eventcategory_bank,{'bank': bank, 'guid1': generateUUIDWithTime(), 'sub_eventcategory': rep_event_group});
                                                        all_rep_event_group += rep_event_group;
                                                    }

                                                    // 所有sounddef
                                                    let count: number = 0;
                                                    let all_rep_sounddef: string = ''
                                                    let soundbasenamemap: Record<string, number> = {};
                                                    for (const soundfile of dict1[fsbname]) { 
                                                        all_rep_sounddef += replacePlaceholders(single_sounddef,{'wav_name': soundfile.basename, 'num': count.toString(), 'guid': generateUUIDWithTime(), 'path': soundfile.fullpath, 'main_file_name': soundfile.fsb_name})
                                                        soundbasenamemap[soundfile.basename] = count;
                                                        count += 1;
                                                    }
                                                    all_rep_sounddef = replacePlaceholders(sounddeffolder,{'guid_folder': generateUUIDWithTime(), 'guid_def': generateUUIDWithTime(), 'sounddefs': all_rep_sounddef})

                                                    // 所有 eventgroup
                                                    let all_rep_eg: string = ''
                                                    for (const groupname in custom_group) {
                                                        let rep_simpleevent: string = '';
                                                        for (const soundfile of custom_group[groupname]) { 
                                                            const basename = soundfile.basename
                                                            const num = soundbasenamemap[basename].toString()
                                                            const catepath = `${soundfile.klei_bank}/${soundfile.klei_group}`
                                                            rep_simpleevent += replacePlaceholders(single_simpleevent, {'basename': basename, 'guid': generateUUIDWithTime(), 'num': num, 'catagories_path': catepath, 'main_file_name': fsbname, 'path': soundfile.fullpath})
                                                        }
                                                        all_rep_eg += replacePlaceholders(single_eventgroup, {'group': groupname, 'guid': generateUUIDWithTime(), 'simpleevent': rep_simpleevent})
                                                    }

                                                    

                                                    await rewriteContent(fdp_path,{
                                                        main_file_name: fsbname,
                                                        guid_main: generateUUIDWithTime(),
                                                        file_num: filenums.toString(),
                                                        guid_music: generateUUIDWithTime(),
                                                        all_eventcategory: all_rep_event_group,
                                                        guid_sounddeffolder: generateUUIDWithTime(),
                                                        guid_sounddef: generateUUIDWithTime(),
                                                    })
                                                }
                                                
                                                break
                                            };
                                            case '2. ':{
                                                // 读取本地文件并显示
                                                const filePath = path.join(__dirname, '..', 'doc', 'fdp.md'); // 或其他文件路径
                                                const fileContent = fs.readFileSync(filePath, 'utf8');

                                                vscode.workspace.openTextDocument({
                                                    content: fileContent,
                                                    language: 'markdown'  // 指定语言模式
                                                }).then(doc => vscode.window.showTextDocument(doc));

                                                vscode.window.showInformationMessage(vscode.l10n.t('src.extension.extra.op.fdp-gener-gen-tutorial'));
                                                // const scmlPath = await selectScmlFile();
                                                // console.log(scmlPath);
                                                // if (!scmlPath) {
                                                //     return;
                                                // } else {
                                                //     await op_crop_all(scmlPath);
                                                // }
                                                break
                                            };
                                        }
                                    }
                                    quickpick_5.dispose();
                                });
                                quickpick_5.show();
                                break
                            };
                        }
                    }
                    quickpick.dispose(); // 关闭 QuickPick
                });
                // 显示 QuickPick
                quickpick.show();
            } else {
                vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.fail_to_find_modinfo'));
                return;
            };
        } else {
            vscode.window.showErrorMessage(vscode.l10n.t('src.extension.compiler.didnt_open_any_editor'));
            return;
        };
        return;

    });

    // const disposableCreateAtlas = vscode.commands.registerCommand('dst-lan.create-atlas', async () => {
    //     const activeEditorPath = getAcitveEditor();
    //     if (activeEditorPath) { // 有激活的编辑器
    //         const directoryPath = path.dirname(activeEditorPath);
    
    //         // 弹出输入框,让玩家输入文件夹名称
    //         const folderName = await vscode.window.showInputBox({
    //             prompt: 'Enter folder name containing PNG images',
    //             placeHolder: 'Folder name'
    //         });
    //         // 如果用户取消了输入，则不执行任何操作并返回
    //         if (folderName === undefined) { return; }
    
    //         // 如果为空
    //         if (folderName === '') {
    //             vscode.window.showErrorMessage('Folder name cannot be empty');
    //             return;
    //         }
    
    //         // 如果当前文件夹不存在，则提示用户并返回
    //         if (!fs.existsSync(genPath(directoryPath, folderName))) {
    //             vscode.window.showErrorMessage('Folder does not exist');
    //             return;
    //         }
    
    //         const pngPaths = await getScmlPngFilePaths(genPath(directoryPath, folderName));
    //         if (pngPaths.length === 0) {
    //             vscode.window.showErrorMessage('No PNG files found in the folder');
    //             return;
    //         }
    
    //         const { canvas, atlasInfo } = await createAtlas(pngPaths);
    //         const atlasPath = genPath(directoryPath, folderName, 'atlas.png');
    //         const xmlPath = genPath(directoryPath, folderName, 'atlas.xml');
    
    //         // 保存图集图片
    //         const out = fs.createWriteStream(atlasPath);
    //         const stream = canvas.createPNGStream();
    //         stream.pipe(out);
    
    //         out.on('finish', async () => {
    //             // 生成XML文件
    //             await generateAtlasXml(atlasInfo, xmlPath);
    //             vscode.window.showInformationMessage('Atlas created successfully');
    //         });
    //     } else {
    //         vscode.window.showErrorMessage('No active editor found');
    //         return;
    //     }
    // });

    context.subscriptions.push(disposable, disposableToggleLang, disposable_custom_regex,disposableRemoveComments,disposable_help,disposableCompiler,disposable_makeimg,disposableExtraFn);
};
/////////////////////////////////////////
/**
 * 动态生成配置文件 
 * @param {string} dir_file_path - 文件夹的路径
 * @param {string} content - 内容
 * @returns {Promise<string>} - 生成的配置文件路径
 */
async function genConfigFile(dir_file_path:string,content:string): Promise<string> {
    let homeDir: string | undefined;

    // 检查每个环境变量是否已定义
    if (process.env.USERPROFILE) {
        homeDir = process.env.USERPROFILE;
    } else if (process.env.HOMEDRIVE && process.env.HOMEPATH) {
        homeDir = process.env.HOMEDRIVE + process.env.HOMEPATH;
    } else {
        // 设置一个默认值，例如当前目录
        homeDir = process.cwd();
    }
    const dstLanDir = path.join(homeDir, 'Documents', 'dst-lan');
    const configFilePath = path.join(dstLanDir, dir_file_path);

    // 创建 dst-lan 目录
    if (!fs.existsSync(dstLanDir)) {
        fs.mkdirSync(dstLanDir, { recursive: true });
    }

    fs.writeFileSync(configFilePath, content, 'utf8');

    return configFilePath;
};

/**
 * 读取配置文件
 * @param {string} configFile - 配置文件名字
 * @returns {Promise<string | null>} - 读取到的内容，如果文件不存在则返回 null
 */
async function readConfigFile(configFile:string): Promise<string | null> {
    let homeDir: string | undefined;

    // 检查每个环境变量是否已定义
    if (process.env.USERPROFILE) {
        homeDir = process.env.USERPROFILE;
    } else if (process.env.HOMEDRIVE && process.env.HOMEPATH) {
        homeDir = process.env.HOMEDRIVE + process.env.HOMEPATH;
    } else {
        // 设置一个默认值，例如当前目录
        homeDir = process.cwd();
    }
    const dstLanDir = path.join(homeDir, 'Documents', 'dst-lan');
    const configFilePath = path.join(dstLanDir, configFile);

    if (!fs.existsSync(configFilePath)) {
        return null;
    }

    const content = fs.readFileSync(configFilePath, 'utf8').trim();
    return content;
}


// 动态生成配置文件路径
function getConfigFilePath_compiler(): string {
    let homeDir: string | undefined;

    // 检查每个环境变量是否已定义
    if (process.env.USERPROFILE) {
        homeDir = process.env.USERPROFILE;
    } else if (process.env.HOMEDRIVE && process.env.HOMEPATH) {
        homeDir = process.env.HOMEDRIVE + process.env.HOMEPATH;
    } else {
        // 设置一个默认值，例如当前目录
        homeDir = process.cwd();
    }
    const dstLanDir = path.join(homeDir, 'Documents', 'dst-lan');
    const configFilePath = path.join(dstLanDir, 'compilerpath.ini');

    // 创建 dst-lan 目录
    if (!fs.existsSync(dstLanDir)) {
        fs.mkdirSync(dstLanDir, { recursive: true });
    }

    return configFilePath;
};
/**
 * 获取指定文件夹下的所有文件名，可以选择是否去掉文件名后缀
 * @param {string} directory - 文件夹的路径
 * @param {boolean} [noext=false] - 是否去掉文件名后缀
 * @returns {string[]} 文件名列表
 */
function getFilesInDirectory(directory: string, noext: boolean = false): string[] {
    try {
        // 读取目录内容
        const files = fs.readdirSync(directory);

        // 过滤掉 . 和 .. 目录条目
        let filteredFiles = files.filter(file => file !== '.' && file !== '..');

        // 如果 noext 为 true，去掉文件名后缀
        if (noext) {
            filteredFiles = filteredFiles.map(file => path.basename(file, path.extname(file)));
        }

        return filteredFiles;
    } catch (error) {
        console.error(`Error reading directory ${directory}:`, error);
        return [];
    }
};
// 读取配置文件tools
function readConfigFile_compiler(): string | null {
    if (!fs.existsSync(getConfigFilePath_compiler())) {
        return null;
    }

    const content = fs.readFileSync(getConfigFilePath_compiler(), 'utf8').trim();
    return content;
};
// 写入配置文件tools
function writeConfigFile_compiler(path: string): void {
    fs.writeFileSync(getConfigFilePath_compiler(), path, 'utf8');
};
// 检查路径是否存在tools
function checkPathExists_compiler(path: string): boolean {
    return fs.existsSync(path);
};
////////////////////////////////
function getSubdirectories(directory: string): string[] {
    const subdirectories: string[] = [];
    const files = fs.readdirSync(directory, { withFileTypes: true });

    for (const file of files) {
        if (file.isDirectory()) {
            subdirectories.push(path.join(directory, file.name));
        }
    }

    return subdirectories;
}
//////////////////////////////////
// 读取txt
function readFile(path:string): string | null {
    if (!fs.existsSync(path)) {
        return null;
    }
    const content = fs.readFileSync(path, 'utf8').trim();
    return content;
};
// 生成内部路径
function genPathIn(...args: string[]): string {
    return path.join(__dirname,'..', ...args)
};
// 生成路径
function genPath(...args: string[]): string {
    return path.join(...args)
};
// 替换%(id)s格式的占位符
function regexRep(text:string, ph:string, after:string): string{
    return text.replace(new RegExp(`%\\(${ph}\\)s`, 'g'), after);
};

function replacePlaceholders(template: string, replacements: Record<string, string>): string {
    let result = template;
    for (const [placeholder, replacement] of Object.entries(replacements)) {
        // 支持 %(placeholder)s 格式
        result = result.replace(new RegExp(`%\\(${placeholder}\\)s`, 'g'), replacement);
    }
    return result;
};

// 生成文件
function genFile(...args: string[]): string{
    const tarpath = path.join(...args)
    if (!fs.existsSync(tarpath)) {
        fs.mkdirSync(tarpath, { recursive: true });
    }
    return tarpath;
};
// // 写入文件
// function writeContent(content: string,path: string): void {
//     fs.writeFileSync(content, path, 'utf8');
// };
// 创建并写入文件
async function writeContent(filePath: string,content: string): Promise<void> {
    await fs.promises.writeFile(filePath, content);
};

// 复制后的文件的替换符更改
// async function rewriteContent(filePath: string, ph:string, after:string) {
//     // writeContent(genPath(groundPath,`${prefabName}.scml`),regexRep(readFile(genPathIn('resource','scml','ground.scml'))||'','prefab',prefabName));
//     writeContent(filePath,regexRep(readFile(filePath)||'',ph,after))
// }
// 重写的 rewriteContent 函数
async function rewriteContent(filePath: string, replacements: { [key: string]: string }): Promise<void> {
    try {
        // 读取文件内容
        let content = readFile(filePath);

        // 遍历字典，依次替换占位符
        for (const [placeholder, replacement] of Object.entries(replacements)) {
            content = regexRep(content||'', placeholder, replacement);
        }

        // 写回文件
        await writeContent(filePath, content||'');

        // 打印修改后的文件内容，以便调试
        // console.log(`Modified content for ${filePath}: ${content}`);
    } catch (error) {
        // vscode.window.showErrorMessage(`Error rewriting content: ${error}`);
    }
}

function getAcitveEditor(): string | undefined {
    const activeEditor = vscode.window.activeTextEditor;
    if (activeEditor) {
        return activeEditor.document.uri.fsPath;
    }
    return undefined;
};
async function copyFile(sourcePath: string, tarPath: string): Promise<void> {
    try {
        const sourceFilePath = path.join(sourcePath);
        const targetFilePath = path.join(tarPath);
        if (fs.existsSync(sourceFilePath)) {
            await fs.promises.copyFile(sourceFilePath, targetFilePath);
        }
    } catch (error) {
        vscode.window.showErrorMessage(`error: ${error}`);
    }
};
/**
 * 重命名文件夹
 * @param {string} oldFolderPath - 旧文件夹的路径
 * @param {string} newFolderName - 新文件夹的名字
 */
async function renameFolder(oldFolderPath: string, newFolderName: string): Promise<void> {
    try {
        // 构建新文件夹的完整路径
        const newFolderPath = path.join(path.dirname(oldFolderPath), newFolderName);

        // 检查旧文件夹是否存在
        try {
            await fs.promises.access(oldFolderPath, fs.constants.F_OK);
        } catch (error) {
            // vscode.window.showErrorMessage(vscode.l10n.t('src.extension.rename_folder_error_path_not_exist'));
            return;
        }

        // 检查新文件夹是否已经存在
        try {
            await fs.promises.access(newFolderPath, fs.constants.F_OK);
            // vscode.window.showErrorMessage(vscode.l10n.t('src.extension.rename_folder_error_already_exists'));
            return;
        } catch (error) {
            // 新文件夹不存在，继续重命名
        }

        // 重命名文件夹
        await fs.promises.rename(oldFolderPath, newFolderPath);

        // 显示成功消息
        // vscode.window.showInformationMessage(`文件夹已成功重命名为 ${newFolderName}`);
    } catch (error) {
        // vscode.window.showErrorMessage(`error: ${error}`);
    }
};
/**
 * 重命名文件
 * @param {string} oldFilePath - 旧文件的路径
 * @param {string} newFileName - 新文件的名字
 */
async function renameFile(oldFilePath: string, newFileName: string): Promise<void> {
    try {
        // 构建新文件的完整路径
        const newFilePath = path.join(path.dirname(oldFilePath), newFileName);

        // 检查旧文件是否存在
        try {
            await fs.promises.access(oldFilePath, fs.constants.F_OK);
        } catch (error) {
            // vscode.window.showErrorMessage(vscode.l10n.t('src.extension.rename_file_error_path_not_exist'));
            return;
        }

        // 检查新文件是否已经存在
        try {
            await fs.promises.access(newFilePath, fs.constants.F_OK);
            // vscode.window.showErrorMessage(vscode.l10n.t('src.extension.rename_file_error_already_exists'));
            return;
        } catch (error) {
            // 新文件不存在，继续重命名
        }

        // 重命名文件
        await fs.promises.rename(oldFilePath, newFilePath);

        // 显示成功消息
        // vscode.window.showInformationMessage(`文件已成功重命名为 ${newFileName}`);
    } catch (error) {
        // vscode.window.showErrorMessage(`error: ${error}`);
    }
};
/**
 * 异步读取文件，进行正则替换，并将修改后的内容写回文件
 * @param filePath - 文件路径
 * @param regex - 正则表达式
 * @param replacement - 替换内容
 */
async function replaceInFile(filePath: string, regex: RegExp, replacement: string): Promise<void> {
    try {
        // 读取文件内容
        const content = await fs.promises.readFile(filePath, 'utf8');

        // 进行正则替换
        const newContent = content.replace(regex, replacement);

        // 将修改后的内容写回文件
        await fs.promises.writeFile(filePath, newContent, 'utf8');

        // 打印成功消息
        console.log(`文件 ${filePath} 已成功修改`);
    } catch (error) {
        console.error(`Error replacing in file ${filePath}:`, error);
        throw error;
    }
};
/**
 * 获取指定文件夹中的所有文件，并用正则表达式筛选文件名（不递归）
 * @param directoryPath - 文件夹路径
 * @param regex - 正则表达式
 * @returns 符合条件的文件路径数组
 */
function getFilesByRegex(directoryPath: string, regex: RegExp): string[] {
    const matchedFiles: string[] = [];

    try {
        // 读取目录内容
        const files = fs.readdirSync(directoryPath, { withFileTypes: true });

        for (const file of files) {
            const filePath = path.join(directoryPath, file.name);

            if (file.isFile() && regex.test(file.name)) {
                // 如果是文件且文件名匹配正则表达式，则添加到结果数组
                matchedFiles.push(filePath);
            }
        }
    } catch (error) {
        console.error(`Error reading directory ${directoryPath}:`, error);
        throw error;
    }

    return matchedFiles;
}
//////////////////////////////////
function findScmlFilesInSubdirectories(directories: string[]): string[] {
    const scmlFiles: string[] = [];

    directories.forEach(directory => {
        const files = fs.readdirSync(directory);

        for (const file of files) {
            const filePath = path.join(directory, file);
            if (fs.statSync(filePath).isFile() && path.extname(file) === '.scml') {
                scmlFiles.push(filePath);
            }
        }
    });

    return scmlFiles;
}

function getValidPngFiles(directoryPath: string): string[] {
    const validPngFiles: string[] = [];

    function processDirectory(dirPath: string) {
        const files = fs.readdirSync(dirPath);

        for (const file of files) {
            const filePath = path.join(dirPath, file);
            const stats = fs.statSync(filePath);

            if (stats.isDirectory()) {
                // 递归处理子目录
                processDirectory(filePath);
            } else if (file.endsWith('.png')) {
                const baseName = path.basename(file, '.png');
                const texFilePath = path.join(dirPath, `${baseName}.tex`);

                try {
                    const texStats = fs.statSync(texFilePath);
                    if (texStats.isFile()) {
                        // 如果有同名的 .tex 文件，则排除该 .png 文件
                        continue;
                    }
                } catch (error) {
                    // 如果没有 .tex 文件，则保留该 .png 文件
                    validPngFiles.push(filePath);
                }
            }
        }
    }

    processDirectory(directoryPath);
    return validPngFiles;
}

async function executeCommand(command: string, prefix: string): Promise<void> {
    const { exec } = require('child_process');

    return new Promise((resolve, reject) => {
        exec(command, (error: Error | null, stdout: string | Buffer, stderr: string | Buffer) => {
            if (error) {
                vscode.window.showErrorMessage(`Error executing command: ${error.message}\n${stderr}`);
                return reject(error);
            }
            const output = `${stdout.toString()}\n${stderr.toString()}`;
            displayOutputLines(output,prefix);
            resolve();
        });
    });
};
function displayOutputLines(output: string, prefix: string): void {
    const lines = output.split('\n');
    let index = 0;

    const displayNextLine = () => {
        if (index < lines.length) {
            vscode.window.setStatusBarMessage(`${prefix}${lines[index]}`,500);
            index++;
            setTimeout(displayNextLine, 500); // 每隔500毫秒显示下一行
        }
    };

    displayNextLine();
};
function findModInfoFile(startPath: string): string | undefined {
    // let currentPath = startPath;

    // while (currentPath !== '/') {
    //     const modInfoPath = path.join(currentPath, 'modinfo.lua');

    //     if (fs.existsSync(modInfoPath)) {
    //         return currentPath;
    //     }

    //     currentPath = path.dirname(currentPath);
    // }

    // return undefined;
    const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
    if (!workspaceFolder) {return undefined;};
    const wpfolder = workspaceFolder.uri.fsPath;
    // vscode.window.showInformationMessage(`${workspaceFolder.uri.fsPath}`);
    if (!startPath) {
        return undefined; // 处理空路径的情况
    };

    let currentPath = startPath;

    while (currentPath !== '/') {
        
        const modInfoPath = path.join(currentPath, 'modinfo.lua');
        // vscode.window.showInformationMessage(`${workspaceFolder}`);
        if (fs.existsSync(modInfoPath)) {
            return currentPath;
        }

        if (currentPath === wpfolder) {return undefined;}; // 先检测有没有modinfo 再判断在不在wp的根目录

        currentPath = path.dirname(currentPath);
        // vscode.window.showInformationMessage(`${currentPath}`);
        // 如果当前路径已经是根目录，直接返回 undefined
        if (currentPath === '/') {
            // vscode.window.showInformationMessage('根目录');
            return undefined;
        }
    }

    return undefined;
};


function removeComments(text: string): string {
    // 先去多行的注释 但是在单行
    const runar_q = /--\[.*?\[.*?\].*?\]/g;
    // 多行 沟槽的正则 沟槽的ts 踩了一堆坑 注意匹配模式
    const multiLineCommentRegex = /--\[.*?\[((.*?\].*?\].*?[\r\n])|(.*?[\r\n]))*?(.*?\].*?\])/g;
    // 单行
    const singleLineCommentRegex = /--.*/g;
    // 空行 注意从头开始
    const emptyLineRegex = /^\s*[\r\n]/gm;
    //////////////
    let newText = text.replace(runar_q, '');
    // 移除多行注释
    newText = newText.replace(multiLineCommentRegex, '');
    // 移除单行注释
    newText = newText.replace(singleLineCommentRegex, '');
    // 移除空行
    newText = newText.replace(emptyLineRegex, '');

    return newText;
}
// let newLanguage = 'zh-cn';

async function toggleLanguage(): Promise<void> {
    // const currentLanguage = vscode.env.language;
    // vscode.window.showInformationMessage(currentLanguage)
    // let newLanguage: string;
    let cur_lang: string;
    (async () => {
        try {
            cur_lang = await readLangFile();
            // vscode.window.showWarningMessage(cur_lang);

            if (cur_lang === 'zh-cn') {
                // newLanguage = 'en';
                copySingleFile(path.join(__dirname, '..', 'snippets_backup', 'snippets_en.code-snippets'), path.join(__dirname, '..', 'snippets', 'snippets.code-snippets'));
                copySingleFile(path.join(__dirname, '..', 'custom_rules_backup', 'rules_en.json'), path.join(__dirname, '..', 'custom_rules', 'rules.json'));
                copySingleFile(path.join(__dirname, '..', 'custom_rules_backup', 'help_en.json'), path.join(__dirname, '..', 'custom_rules', 'help.json'));
                writeLangFile('en')
                vscode.window.showWarningMessage('dst-lan: Please restart VSCode to complete the code-snippets language switch.');
                vscode.window.showInformationMessage('Switch to English/切换到英文', vscode.l10n.t('src.extension.switch_btn_title'))
                    .then(button => {
                        if (button === vscode.l10n.t('src.extension.switch_btn_title')) {
                            vscode.window.showWarningMessage(vscode.l10n.t('src.extension.switch_btn_info'));
                            vscode.commands.executeCommand('workbench.action.reloadWindow');
                        }
                    }
                    );



            } else {
                // newLanguage = 'zh-cn';
                copySingleFile(path.join(__dirname, '..', 'snippets_backup', 'snippets_cn.code-snippets'), path.join(__dirname, '..', 'snippets', 'snippets.code-snippets'));
                copySingleFile(path.join(__dirname, '..', 'custom_rules_backup', 'rules_cn.json'), path.join(__dirname, '..', 'custom_rules', 'rules.json'));
                copySingleFile(path.join(__dirname, '..', 'custom_rules_backup', 'help_cn.json'), path.join(__dirname, '..', 'custom_rules', 'help.json'));
                writeLangFile('zh-cn')
                vscode.window.showWarningMessage('dst-lan: 已切换到中文,请立即重启 VSCode 以应用更改!');
                vscode.window.showInformationMessage('Switch to Chinese/切换到中文', vscode.l10n.t('src.extension.switch_btn_title'))
                    .then(button => {
                        if (button === vscode.l10n.t('src.extension.switch_btn_title')) {
                            vscode.window.showWarningMessage(vscode.l10n.t('src.extension.switch_btn_info'));
                            vscode.commands.executeCommand('workbench.action.reloadWindow');
                        }
                    }
                    );

            }

        } catch (error) {
            vscode.window.showWarningMessage(`error: ${error}`);
        }
    })();



    // vscode.commands.executeCommand('workbench.action.selectLanguage', newLanguage);
}

async function copyFolder(source: string, target: string, excludeFiles: string[]): Promise<void> {
    // 创建目标文件夹
    await fs.promises.mkdir(target, { recursive: true });

    // 获取源文件夹的内容
    const files = await fs.promises.readdir(source, { withFileTypes: true });

    for (const file of files) {
        const sourcePath = path.join(source, file.name);
        const targetPath = path.join(target, file.name);

        // 检查是否为需要排除的文件
        if (excludeFiles.includes(file.name)) {
            continue;
        }

        if (file.isDirectory()) {
            // 如果是目录，则递归复制
            await copyFolder(sourcePath, targetPath, excludeFiles);
        } else {
            // 如果是文件，则直接复制
            await fs.promises.copyFile(sourcePath, targetPath);
        }
    }
}

async function copySingleFile(sourcePath: string, tarPath: string): Promise<void> {
    try {
        // 源文件夹路径
        // const snippetsBackupPath = path.join(sourcePath, 'snippets_backup');

        // // 目标文件夹路径
        // const snippetsPath = path.join(sourcePath, 'snippets');

        // // 检查目标文件夹是否存在，不存在则创建
        // if (!fs.existsSync(snippetsPath)) {
        //     await fs.promises.mkdir(snippetsPath, { recursive: true });
        // }

        // 源文件路径
        const sourceFilePath = path.join(sourcePath);

        // 目标文件路径
        const targetFilePath = path.join(tarPath);

        // 检查源文件是否存在
        if (!fs.existsSync(sourceFilePath)) {
            vscode.window.showErrorMessage(vscode.l10n.t('src.extension.copy_snippest_error_path_not_exist'));
            return;
        }

        // 拷贝文件
        await fs.promises.copyFile(sourceFilePath, targetFilePath);

        // vscode.window.showInformationMessage(`文件 ${tarPath} 已成功拷贝`);
    } catch (error) {
        vscode.window.showErrorMessage(`error: ${error}`);
    }
}

function writeLangFile(content: string): Promise<void> {
    return new Promise((resolve, reject) => {
        fs.writeFile(path.join(__dirname, 'lang.ini'), content, 'utf8', (err) => {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        });
    });
}

function readLangFile(): Promise<string> {
    return new Promise((resolve, reject) => {
        fs.readFile(path.join(__dirname, 'lang.ini'), 'utf8', (err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
    });
}
//------------------------------OP2-------------------------------------
// 打包文件夹的函数
async function packCurrentDirectory(sourcePath: string, excludePaths: string[]): Promise<void> {
    try {
        // 获取当前目录的文件夹名字
        const dirName = path.basename(sourcePath);
        // 获取当前时间并格式化为字符串
        const now = new Date();
        const formattedTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}_${String(now.getDate()).padStart(2, '0')}-${String(now.getHours()).padStart(2, '0')}-${String(now.getMinutes()).padStart(2, '0')}`;
        const zipFilename = `${dirName}_${formattedTime}.zip`;

        // 获取完整路径
        const zipFilePath = path.join(sourcePath, zipFilename);

        // 创建输出流
        const output = fs.createWriteStream(zipFilePath);
        const archive = archiver('zip', {
            zlib: { level: 9 } // 设置压缩级别
        });

        archive.pipe(output);

        // 添加所有非空和空的目录到归档
        await addDirectoriesToArchive(archive, sourcePath, '', excludePaths);

        // 完成归档
        return new Promise((resolve, reject) => {
            output.on('finish', () => {
                console.log(`Successfully created archive: ${zipFilePath}`);
                vscode.window.showInformationMessage(`Successfully created archive: ${zipFilePath}`);
                resolve();
            });
            archive.on('error', (err) => {
                console.error(`Error creating archive: ${err.message}`);
                vscode.window.showErrorMessage(`Failed to create archive: ${err.message}`);
                reject(err);
            });
            archive.finalize();
        });
    } catch (error) {
        if (error instanceof Error) {
            console.error(`Error adding directory to archive: ${error.message}`);
        } else {
            console.error('An unknown error occurred while adding directory to archive.');
        }
    }
}

// 递归添加目录到归档，并处理空目录
async function addDirectoriesToArchive(archive: archiver.Archiver, dirPath: string, baseDir: string, excludePaths: string[]): Promise<void> {
    try {
        // 检查是否在排除列表中
        if (excludePaths.includes(dirPath)) {
            return;
        }

        // 遍历目录中的文件和子目录
        for (const root of fs.readdirSync(dirPath, { withFileTypes: true })) {
            const fullPath = path.join(dirPath, root.name);
            const relativePath = baseDir ? path.join(baseDir, root.name) : root.name;

            if (root.isDirectory()) {
                // 递归处理子目录
                await addDirectoriesToArchive(archive, fullPath, relativePath, excludePaths);
                // 添加空目录到归档
                if (!fs.readdirSync(fullPath).length) {
                    archive.append('', { name: `${relativePath}/` });
                }
            } else if (root.isFile()) {
                // 添加文件到归档
                archive.file(fullPath, { name: relativePath });
            }
        }
    }  catch (error) {
        if (error instanceof Error) {
            console.error(`Error adding directory to archive: ${error.message}`);
        } else {
            console.error('An unknown error occurred while adding directory to archive.');
        }
    }
}
//------------------------------OP3-------------------------------------
async function expandCanvas(inputPath: string, outputPath: string) {
    try {
        console.log(`Attempting to expand canvas for image at ${inputPath} and save to ${outputPath}`);
        
        const metadata = await sharp(inputPath).metadata();
        if (!metadata.width || !metadata.height) {
            throw new Error('Image metadata does not contain width or height');
        }

        const originalWidth = metadata.width;
        const originalHeight = metadata.height;

        // 计算需要扩展的宽度和高度，使其放大一倍
        const expandWidth = originalWidth;
        const expandHeight = originalHeight;

        await sharp(inputPath)
            .extend({
                top: expandHeight / 2,
                bottom: expandHeight / 2,
                left: expandWidth / 2,
                right: expandWidth / 2,
                background: { r: 0, g: 0, b: 0, alpha: 0 } // 透明背景
            })
            .toFile(outputPath);
        console.log(`Successfully expanded canvas and saved to ${outputPath}`);
    } catch (error) {
        if (error instanceof Error) {
            vscode.window.showErrorMessage(`Error expanding canvas: ${error.message}`);
        } else {
            vscode.window.showErrorMessage('An unknown error occurred while expanding canvas.');
        }
    }
}
/**
 * 强制扩展图像的画布,覆盖原文件,无备份
 * @param {string} inputPath 
 */
async function expandCanvasForce(inputPath: string): Promise<{ orig_width: number, orig_height: number }> {
    try {
        // console.log(`Attempting to expand canvas for image at ${inputPath}`);
        
        const metadata = await sharp(inputPath).metadata();
        if (!metadata.width || !metadata.height) {
            throw new Error('Image metadata does not contain width or height');
        }

        const originalWidth = metadata.width;
        const originalHeight = metadata.height;

        // 计算需要扩展的宽度和高度，使其放大一倍
        const expandWidth = originalWidth;
        const expandHeight = originalHeight;

        // 创建临时文件路径
        const tempPath = `${inputPath}.tmp`;

        // 将处理后的图像保存到临时文件
        await sharp(inputPath)
            .extend({
                top: Math.floor(expandHeight / 2),
                bottom: Math.floor(expandHeight / 2),
                left: Math.floor(expandWidth / 2),
                right: Math.floor(expandWidth / 2),
                background: { r: 0, g: 0, b: 0, alpha: 0 } // 透明背景
            })
            .toFile(tempPath);

        // 删除原始文件
        await fs.promises.unlink(inputPath);

        // 将临时文件重命名为原始文件名
        await fs.promises.rename(tempPath, inputPath);

        // console.log(`Successfully expanded canvas and saved to ${inputPath}`);

        // 返回原画布的宽度和高度
        return { orig_width: originalWidth, orig_height: originalHeight };
    } catch (error) {
        if (error instanceof Error) {
            vscode.window.showErrorMessage(`Error expanding canvas: ${error.message}`);
        } else {
            vscode.window.showErrorMessage('An unknown error occurred while expanding canvas.');
        }
        // 返回默认值或抛出异常
        return { orig_width: 0, orig_height: 0 };
    }
}

/**
 * 强制裁剪图像的画布,覆盖原文件,无备份
 * @param {string} inputPath 
 */
async function cropCanvasForce(inputPath: string): Promise<{ newWidth: number, newHeight: number, topTrim: number, bottomTrim: number, leftTrim: number, rightTrim: number }> {
    try {
        // 获取图片的元数据
        const metadata = await sharp(inputPath).metadata();

        // 检查元数据中的宽度和高度是否存在
        if (!metadata.width || !metadata.height) {
            throw new Error('Image metadata does not contain width or height');
        }

        const originalWidth = metadata.width;
        const originalHeight = metadata.height;

        // 使用 trim 方法裁剪图片并获取裁剪后的信息
        const { info, data } = await sharp(inputPath)
            .trim()
            .toBuffer({ resolveWithObject: true });

        // 设置默认值以防止未定义情况
        const trimOffsetTop = info?.trimOffsetTop ?? 0;
        const trimOffsetLeft = info?.trimOffsetLeft ?? 0;

        // 计算各个方向裁剪掉的长度
        const topTrim = Math.abs(trimOffsetTop);
        const bottomTrim = originalHeight - info.height - topTrim;
        const leftTrim = Math.abs(trimOffsetLeft);
        const rightTrim = originalWidth - info.width - leftTrim;

        // 创建临时文件路径
        const tempPath = `${inputPath}.tmp`;

        // 将裁剪后的图像保存到临时文件
        await sharp(data)
            .toFile(tempPath);

        // 删除原始文件
        await fs.promises.unlink(inputPath);

        // 将临时文件重命名为原始文件名
        await fs.promises.rename(tempPath, inputPath);

        // 返回裁剪后的图像信息
        return {
            newWidth: info.width,
            newHeight: info.height,
            topTrim: topTrim,
            bottomTrim: bottomTrim,
            leftTrim: leftTrim,
            rightTrim: rightTrim
        };
    } catch (error) {
        if (error instanceof Error) {
            vscode.window.showErrorMessage(`Error cropping canvas: ${error.message}`);
        } else {
            vscode.window.showErrorMessage('An unknown error occurred while cropping canvas.');
        }
        // 返回默认值或抛出异常
        return { newWidth: 0, newHeight: 0, topTrim: 0, bottomTrim: 0, leftTrim: 0, rightTrim: 0 };
    }
}

/**
 * 异步修改XML文件中的特定属性
 * @param xmlFilePath - XML文件的路径
 * @returns {Promise<void>}
 */
async function modifyXmlFile(xmlFilePath: string): Promise<void> {
    try {
        // 读取XML文件内容
        const xmlData = fs.readFileSync(xmlFilePath, 'utf8');

        // 创建一个xml2js解析器实例
        const parser = new xml2js.Parser();

        // 解析XML数据
        parser.parseString(xmlData, (err: any, result: { spriter_data: any; }) => {
            if (err) {
                console.error('Failed:', err);
                return;
            }

            // 解析后的结果是一个JavaScript对象
            console.log('Parsed XML:', result);

            // 访问特定数据
            const spriterData = result.spriter_data;
            const folders = spriterData.folder;

            folders.forEach((folder: { file: any[]; }) => {
                folder.file.forEach((file) => {
                    file.$.width = (parseFloat(file.$.width) * 2).toString();
                    file.$.height = (parseFloat(file.$.height) * 2).toString();
                    file.$.pivot_x = ((parseFloat(file.$.pivot_x) + 0.5) / 2).toFixed(6);
                    file.$.pivot_y = ((parseFloat(file.$.pivot_y) + 0.5) / 2).toFixed(6);
                });
            });

            const builder = new xml2js.Builder();
            const xmlString = builder.buildObject(result);

            fs.writeFileSync(xmlFilePath, xmlString, 'utf8');
        });
    } catch (error) {
        console.error('error:', error);
    }
}
/**
 * 获取scml目录中的所有png文件路径
 * @param {string} directoryPath 
 * @returns {Promise<string[]>} 
 */
async function getScmlPngFilePaths(directoryPath: string): Promise<string[]> {
    const validPngFiles: string[] = [];
    const scmlpath = path.dirname(directoryPath);

    async function processDirectory(dirPath: string) {
        const files = await fs.promises.readdir(dirPath);

        for (const file of files) {
            const filePath = path.join(dirPath, file);
            const stats = await fs.promises.stat(filePath);

            if (stats.isDirectory()) {
                // 递归处理子目录
                await processDirectory(filePath);
            } else if (file.endsWith('.png')) {
                validPngFiles.push(filePath);
                // const baseName = path.basename(file, '.png');
                // const texFilePath = path.join(dirPath, `${baseName}.tex`);

                // try {
                //     const texStats = await fs.promises.stat(texFilePath);
                //     if (texStats.isFile()) {
                //         // 如果有同名的 .tex 文件，则排除该 .png 文件
                //         continue;
                //     }
                // } catch (error) {
                //     // 如果没有 .tex 文件，则保留该 .png 文件
                //     validPngFiles.push(filePath);
                // }
            }
        }
    }

    await processDirectory(scmlpath);
    return validPngFiles;
}

async function op_expand_all(scmlPath: string) {
    const allpngpath = await getScmlPngFilePaths(scmlPath);
    for (const pngpath of allpngpath) {
        // const basename = path.basename(pngpath);
        // const parentfolder_basename = path.basename(path.dirname(pngpath));
        // const name_in_scml = `${parentfolder_basename}/${basename}`
        // console.log(`Processing ${name_in_scml}`);
        await expandCanvasForce(pngpath);
    };
    await modifyXmlFile(scmlPath);
} 

async function op_crop_all(scmlPath: string) {
    const allpngpath = await getScmlPngFilePaths(scmlPath);
    // 定义 map 类型
    let data_map: Record<string, any> = {};
    for (const pngpath of allpngpath) {
        const res = await cropCanvasForce(pngpath)
        const basename = path.basename(pngpath);
        const parentfolder_basename = path.basename(path.dirname(pngpath));
        const name_in_scml = `${parentfolder_basename}/${basename}`
        data_map[name_in_scml] = res;
    };
    try {
        // 读取XML文件内容
        const xmlData = fs.readFileSync(scmlPath, 'utf8');

        // 创建一个xml2js解析器实例
        const parser = new xml2js.Parser();

        // 解析XML数据
        parser.parseString(xmlData, (err: any, result: { spriter_data: any; }) => {
            if (err) {
                console.error('Failed:', err);
                return;
            }

            // 解析后的结果是一个JavaScript对象
            console.log('Parsed XML:', result);

            // 访问特定数据
            const spriterData = result.spriter_data;
            const folders = spriterData.folder;

            folders.forEach((folder: { file: any[]; }) => {
                folder.file.forEach((file) => {
                    const res = data_map[file.$.name];
                    if (res) {
                        const old_width = parseFloat(file.$.width);
                        const old_height = parseFloat(file.$.height);
                        const old_pivot_x = parseFloat(file.$.pivot_x);
                        const old_pivot_y = parseFloat(file.$.pivot_y);

                        file.$.width = (res.newWidth).toString();
                        file.$.height = (res.newHeight).toString();
                        file.$.pivot_x = ((old_pivot_x*old_width-Math.abs(res.leftTrim))/res.newWidth).toFixed(6);
                        file.$.pivot_y = ((old_pivot_y*old_height-Math.abs(res.bottomTrim))/res.newHeight).toFixed(6);
                    };
                });
            });

            const builder = new xml2js.Builder();
            const xmlString = builder.buildObject(result);

            fs.writeFileSync(scmlPath, xmlString, 'utf8');
        });
    } catch (error) {
        console.error('error:', error);
    }
}

// 添加一个新的函数来选择 .scml 文件
async function selectScmlFile(): Promise<string | undefined> {
    const options: vscode.OpenDialogOptions = {
        canSelectMany: false, // 只允许选择一个文件
        filters: {
            'SCML Files': ['scml'] // 过滤器，只显示 .scml 文件
        },
        title: vscode.l10n.t('src.extension.extra.op.select_scml_file')
    };

    const fileUri = await vscode.window.showOpenDialog(options);
    if (fileUri && fileUri.length > 0) {
        return fileUri[0].fsPath; // 返回所选文件的路径
    }
    return undefined; // 如果用户取消选择，则返回 undefined
}

async function readFirstLine(filePath: string): Promise<string> {
    try {
        // 使用utf8编码自动处理BOM
        const content = fs.readFileSync(filePath, 'utf8');
        
        // 处理不同换行格式并获取首行
        const firstNewlineIndex = content.search(/\r?\n/);
        return firstNewlineIndex === -1 
            ? content.trim()       // 没有换行的情况
            : content.slice(0, firstNewlineIndex).trim();
    } catch (error) {
        // 增强错误信息
        throw new Error(`Failed to read first line from ${filePath}: ${error instanceof Error ? error.message : error}`);
    }
}

/**
 * 异步读取文件的第一行和第二行
 * @param filePath - 文件路径
 * @returns {Promise<{ firstLine: string, secondLine: string }>} 包含第一行和第二行内容的对象
 */
async function readFirstTwoLines(filePath: string): Promise<{ firstLine: string, secondLine: string }> {
    try {
        // 使用utf8编码自动处理BOM
        const content = fs.readFileSync(filePath, 'utf8');

        // 分割换行符（支持不同平台的换行格式）
        const lines = content.split(/\r?\n/);

        // 获取第一行和第二行内容，如果不存在则为空字符串
        const firstLine = lines[0] ? lines[0].trim() : '';
        const secondLine = lines[1] ? lines[1].trim() : '';

        return { firstLine, secondLine };
    } catch (error) {
        // 增强错误信息
        throw new Error(`Failed to read first two lines from ${filePath}: ${error instanceof Error ? error.message : error}`);
    }
}

/**
 * 异步替换字符串中的指定字符
 * @param inputString - 传入的字符串
 * @param searchString - 需要替换的字符串
 * @param replaceString - 替换成的字符串
 * @returns {Promise<string>} - 替换后的字符串
 */
async function replaceStringAsync(inputString: string, searchString: string, replaceString: string): Promise<string> {
    return new Promise((resolve) => {
        // 使用同步的字符串替换方法
        const resultString = inputString.split(searchString).join(replaceString);
        // 模拟异步操作
        setTimeout(() => {
            resolve(resultString);
        }, 0);
    });
}


/**
 * 异步递归搜索指定路径下的所有文件
 * @param directoryPath - 要搜索的目录路径
 * @returns Promise<string[]> - 包含所有文件路径的数组
 */
async function getAllFilesRecursively(directoryPath: string): Promise<string[]> {
    const files: string[] = [];

    async function traverse(currentPath: string) {
        try {
            // 读取目录内容
            const entries = await fs.promises.readdir(currentPath, { withFileTypes: true });

            for (const entry of entries) {
                const fullPath = path.join(currentPath, entry.name);
                
                if (entry.isDirectory()) {
                    // 如果是目录，递归遍历
                    await traverse(fullPath);
                } else if (entry.isFile()) {
                    // 如果是文件，添加到结果数组
                    files.push(fullPath);
                }
                // 注意：这里忽略了符号链接等其他类型的文件
            }
        } catch (error) {
            console.error(`Error traversing directory ${currentPath}:`, error);
            // 可以选择继续处理其他目录或抛出错误
        }
    }

    try {
        // 检查路径是否存在且为目录
        const stats = await fs.promises.stat(directoryPath);
        if (!stats.isDirectory()) {
            throw new Error(`${directoryPath} is not a directory`);
        }
        
        // 开始遍历
        await traverse(directoryPath);
        return files;
    } catch (error) {
        console.error(`Error accessing directory ${directoryPath}:`, error);
        throw error;
    }
}

/**
 * 生成一个包含时间因素的 UUID 字符串
 * @param timestamp 可选的时间戳参数，默认使用当前时间
 * @returns 带花括号的 UUID 字符串
 */
function generateUUIDWithTime(timestamp?: number): string {
    // 使用指定时间或当前时间，并添加随机因子
    const time = (timestamp ?? Date.now()) + Math.random() * 1000;
    
    // 创建基于时间的种子
    let seed = time;
    
    // 自定义随机函数，结合时间种子
    const timeRandom = (): number => {
      seed = (seed * 9301 + 49297) % 233280;
      return seed / 233280;
    };
    
    // 生成 UUID
    const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
      const r = (timeRandom() * 16) | 0;
      const v = c === 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
    
    return `{${uuid}}`;
}
/**
 * 从 _temp_fdp 路径中解析出 fsb_name, group, klei_bank, klei_group, soundname
 * @param filePath - 单个文件路径
 * @returns Promise<{ fsb_name: string, group: string, klei_bank: string, klei_group: string, soundname: string, basename: string, fullpath: string } | null> 
 *          解析出的各个部分，如果路径不符合要求则返回 null
 */
async function parseTempFdpPath(filePath: string): Promise<{ 
    fsb_name: string, 
    group: string, 
    klei_bank: string, 
    klei_group: string, 
    soundname: string,
    basename: string,
    fullpath: string
} | null> {
    try {
        // 检查路径是否包含 _temp_fdp
        const tempFdpIndex = filePath.indexOf('_temp_fdp');
        if (tempFdpIndex === -1) {
            return null;
        }
        
        // 获取 _temp_fdp 之后的部分
        const relativePath = filePath.substring(tempFdpIndex + '_temp_fdp'.length + 1);
        if (!relativePath) {
            return null;
        }
        
        // 分割路径
        const pathParts = relativePath.split(path.sep);
        
        // 检查路径是否有足够的部分
        if (pathParts.length < 5) {
            return null;
        }
        
        // 按照要求提取各个部分
        const fsb_name = pathParts[0];           // 第一级目录
        const group = pathParts[1];              // 第二级目录
        const klei_bank = pathParts[2];          // 第三级目录
        const klei_group = pathParts[3];         // 第四级目录
        const soundname = pathParts.slice(4).join(path.sep); // 剩余部分作为 soundname
        
        // 提取不带后缀的文件名
        let basename = '';
        const lastPart = pathParts[pathParts.length - 1];
        if (lastPart) {
            const lastDotIndex = lastPart.lastIndexOf('.');
            if (lastDotIndex !== -1) {
                basename = lastPart.substring(0, lastDotIndex);
            } else {
                basename = lastPart; // 如果没有后缀，整个就是文件名
            }
        }
        
        return {
            fsb_name,
            group,
            klei_bank,
            klei_group,
            soundname,
            basename,
            fullpath: filePath // 添加完整路径
        };
    } catch (error) {
        console.error(`Error parsing path ${filePath}:`, error);
        return null;
    }
}

// 使用示例：
// const result = await parseTempFdpPath('/some/path/_temp_fdp/filename.fsb/character/male/voice_LP01.wav');
// if (result) {
//     console.log('fsb_name:', result.fsb_name);
//     console.log('group:', result.group);
//     console.log('klei_bank:', result.klei_bank);
//     console.log('klei_group:', result.klei_group);
//     console.log('soundname:', result.soundname);
// }
// 使用示例：
// const allFiles = await getAllFilesRecursively(genPath(modInfoDirectory,'_temp_fdp'));
// const pathMapping = await parseTempFdpPaths(allFiles);
// console.log(pathMapping);
// 使用示例：
// const allFiles = await getAllFilesRecursively('/path/to/directory');
// console.log(allFiles);

/* 
async function createAtlas(pngPaths: string[]): Promise<{ canvas: any, atlasInfo: { [key: string]: { u1: number, u2: number, v1: number, v2: number } } }> {
    const padding = 2; // 图片之间的间距
    let atlasWidth = 0;
    let atlasHeight = 0;
    let currentX = 0;
    let currentY = 0;
    let rowHeight = 0;

    const images: { path: string, width: number, height: number, x: number, y: number }[] = [];

    for (const pngPath of pngPaths) {
        const metadata = await sharp(pngPath).metadata();
        if (!metadata.width || !metadata.height) {
            throw new Error(`Image metadata does not contain width or height for ${pngPath}`);
        }

        const width = metadata.width;
        const height = metadata.height;

        // 调整宽度和高度为64的倍数
        const adjustedWidth = Math.ceil(width / 64) * 64;
        const adjustedHeight = Math.ceil(height / 64) * 64;

        // 检查是否需要换行
        if (currentX + adjustedWidth + padding > atlasWidth) {
            currentX = 0;
            currentY += rowHeight + padding;
            rowHeight = 0;
        }

        // 更新图集的宽度和高度
        atlasWidth = Math.max(atlasWidth, currentX + adjustedWidth + padding);
        rowHeight = Math.max(rowHeight, adjustedHeight);

        // 记录图片的位置
        images.push({ path: pngPath, width, height, x: currentX, y: currentY });

        // 更新当前X位置
        currentX += adjustedWidth + padding;
    }

    // 创建图集画布
    const canvas = createCanvas(atlasWidth, currentY + rowHeight + padding);
    const ctx = canvas.getContext('2d');

    // 绘制图片到图集
    for (const image of images) {
        const img = await loadImage(image.path);
        ctx.drawImage(img, image.x, image.y, image.width, image.height);
    }

    // 计算每个图片的UV坐标
    const atlasInfo: { [key: string]: { u1: number, u2: number, v1: number, v2: number } } = {};
    for (const image of images) {
        const u1 = image.x / atlasWidth;
        const u2 = (image.x + image.width) / atlasWidth;
        const v1 = image.y / atlasHeight;
        const v2 = (image.y + image.height) / atlasHeight;

        const basename = path.basename(image.path);
        atlasInfo[basename] = { u1, u2, v1, v2 };
    }

    return { canvas, atlasInfo };
}

async function generateAtlasXml(atlasInfo: { [key: string]: { u1: number, u2: number, v1: number, v2: number } }, outputPath: string): Promise<void> {
    const builder = new xml2js.Builder();
    const atlasData = {
        Atlas: {
            Texture: [{ $: { filename: 'atlas.tex' } }],
            Elements: [
                atlasInfo.map((info, name) => ({
                    Element: [{ $: { name, u1: info.u1.toFixed(7), u2: info.u2.toFixed(7), v1: info.v1.toFixed(7), v2: info.v2.toFixed(7) } }]
                }))
            ]
        }
    };

    const xmlString = builder.buildObject(atlasData);
    fs.writeFileSync(outputPath, xmlString, 'utf8');
}
 */
export function deactivate() { }

module.exports = {
    activate,
    deactivate
};